I'm trying to make a web style button with user control. I need to make User Control's background transparent. How to do this without making controls invisible. Also I'll need transparent Label and PictureBox.
Trying to make something like this:
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent;
All three controls you list already have the ControlStyles.SupportsTransparentBackColor style turned on. Just set the BackColor property in the designer, Web tab. It is very unclear why that's not good enough for you.
It is otherwise an illusion, Windows Forms implements it by asking the Parent control to draw itself in the OnPaintBackground() method so it provides the background pixels. One notable thing that doesn't work is overlapping controls. You only see the Parent pixels, not the pixels of the overlapped control. That's fixable but the code is fugly.
The only other transparency option is Form.TransparencyKey. That's true transparency, implemented by using overlays in the video adapter. Problem is that this only works on toplevel windows. Forms, not controls.
These restrictions are inherent in the Windows Forms rendering model, using individual windows for the controls. A web browser doesn't have that same restriction, it emulates controls by drawing them. Layers of paint, that makes transparency trivial by just not painting. WPF uses that rendering model as well.
If you mean you want "partial transparency", see this for nice solution:
Opacity of Buttons/TextBoxes - VB.NET
(setting the background color using Alpha value)
I know the above sample is VB but it applies to C# as well. :)
You can use this code :
ImageButton() is my constructor.
public ImageButton()
{
InitializeComponent();
this.SetStyle(ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
}
protected override CreateParams CreateParams
{
get
{
CreateParams parms = base.CreateParams;
parms.ExStyle |= 0x20;
return parms;
}
}
Related
I'm trying to create a full screen overlay over the entire screen, which will change the colors / saturation etc. of the entire screen and add some Text and effects. Basically I want to "replace" the entire screen, while the user still has the ability to interact normally with Windows.
Solution 1
The problem however is, that if I simply create a TopMost window over the entire screen, the user will not be able to interact with whatever is beneath this window.
Solution 2
Simply drawing on the desktop buffer doesn't solve the issue either. It will give nasty effects when windows are moved and also will result in heavy motion blur effects as well. This will never look good.
Solution 3
Hooking the "desktop draw event" is not possible in C# as I would have to inject a DLL into explorer.exe. This is not at all a pretty solution and will not work with C#. Also anti virus programs will likely detect it as something harmfull.
The closest thing I saw was this, but it the user will not be able to "click through" the overlay. In the example the overlay is mostly entirely transparent. Using a color other than the transparency key will result in the problem of Solution 1.
Question: How can I overlay the entire screen with effects efficiently?
UNTESTED
It sounds like your problem is clicking. In order to pass through your mouse messages, have you considered intercepting the mouse click on your top window, (assuming this has been set to be a transparent window), then hiding your window, fire the same mouse message using the user32 import SendMessage, and then showing your window again? If you don't want to hide your window, you can probably just call SendMessage directly to the various other window handles.
The following link shows how to cycle through the windows on the desktop of your application:
http://support.microsoft.com/kb/183009
I think you can also override the CreateParams if you have already made your form transparent. Doing so may allow the mouse events to pass through.
// This may be even simpler
protected override CreateParams CreateParams
{
get
{
CreateParams createParams = base.CreateParams;
createParams.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
return createParams;
}
}
You can make the form itself transparent in newer windows forms like:
public void MakeSeeThru()
{
frmTransparentForm.Opacity = 0.83;
}
The above only works on Form. To do this on child controls takes more work. First you have to set the style to support transparent back color.
public TransparentControl()
{
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
this.BackColor = Color.Transparent.
}
If the control is transparent, this does not stop you from overriding the OnPaintBackground and OnPaint methods and do your custom drawing if you like. It just draws with the default as a see-through background.
I've done this before and there is a bit of a blur if this moves around. However if the entire thing is a huge transparent form that covers your desktop there should be no motion blur.
If that has performance problems and you want to custom draw the desktop, you can grab a screenshot like:
ScreenCapture sc = new ScreenCapture();
// capture entire screen, and save it to a file
Image img = sc.CaptureScreen();
You will need to hide your form first though, so that will likely cause a flicker.
I have some questions regarding flickering and the general flow of UI updates
when multiple objects are involved.
Background:
We use a C# assembly inside a Progress ABL application to drive the UI.
Additionally we use Infragistics controls, as they can easily be styled.
We have a kind of self made MDI. (tab) panels contain multiple user controls which
are used as "Forms".
(Note: Real forms could not be used, because a non-toplevel form has problems handling mouse clicks correctly)
The tabs are realized by an Infragistics UltraDockManager.
On such an UserControl "form" a Progress .Net Control is placed which embeds real Progress Frames.
So we could re-use existing Progress Forms instead of rebuilding them in .NET from scratch.
To make things worse we use a tiled backgroundimage on the (tab) panels.
Now we have the problem that the contents of the panel (derived from Infragistics.Win.Misc.UltraPanel)
are flickering heavily. (Especially when the main application is resized)
Some controls (especially the Progress controls) are deleted and redrawn.
I could get rid of the flickering by using WS_CLIPCHILDREN and WS_EX_COMPOSITED
(as mentioned by Hans Passant in How to fix the flickering in User controls ) in the panel and the UserControl.
But the application was noticeably slower than before, so I had to removed the code again.
I tried setting the Styles of the panel and the UserControl, with absolutely no effect.
this.SetStyle(ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint |
ControlStyles.OptimizedDoubleBuffer |
ControlStyles.ResizeRedraw, true);
Trying to ignore WM_ERASEBKGND in the panel and the UserControl seems not to have an effect either.
protected override void WndProc(ref Message m)
{
if (m.Msg != WM_ERASEBKGND)
{
base.WndProc(ref m);
}
}
What would be the correct way to handle the redrawing of all those objects to reduce the flickering?
I thought about using SendMessage and WM_SETREDRAW. But I am not sure where to put it
in this scenario and whether it would really help or not.
When the application is resized each UserControl seems to be repainted, regardless of its visibility. (Could be scrolled half way out of view)
Why isn't there some kind of clipping going on? The panel should know that some areas don't need to be refreshed or am I mistaken?
I would appreciate any suggestion.
We finally managed to get rid of the flickering.
There were two factors which caused the problem:
Use of Color:Transparent
Use of the AutoScroll feature of the panels
We removed the transparent color and disabled the AutoScroll during resize.
try using this in the program
It may not give the speed in between the redraw events
but it will certainly will look graceful as redrawn activity will take place after all the painting is done
you just need to add it into your main form.
protected override System.Windows.Forms.CreateParams CreateParams
{
get
{
System.Windows.Forms.CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x02000000;
return cp;
}
}
have a look at this and this
They are about calling SuspendLayout on Resize
How I make a background transparent on my form? Is it possible in C#?
Thanks in advance!
You can set the BackColor of your form to an uncommon color (say Color.Magenta) then set the form's TransparencyKey property to the same color. Then, set the FormBorderStyle to None.
Of course, that's just the quick and easy solution. The edges of controls are ugly, you have to keep changing the background color of new controls you add (if they're Buttons or something like that) and a whole host of other problems.
It really depends what you want to achieve. What is it? If you want to make a widget sort of thing, there are much better ways. If you need rounded corners or a custom background, there are much better ways. So please provide some more information if TransparencyKey isn't quite what you had in mind.
Put the following in the constructor of the form:
public Form1()
{
this.TransparencyKey = Color.Turquoise;
this.BackColor = Color.Turquoise;
}
Note: This method prevents you from clicking through the form.
Update:
How to: Give Your Control a Transparent Background
Deprecated:
How to: Create Transparent Windows Forms:
Note: As transparent forms are only supported in Windows 2000 or
later, Windows Forms will be
completely opaque when run on older
operating systems, such as Windows 98,
regardless of the value set for the
Opacity property.
A simple solution to get a transparent background in a winform is to overwrite the OnPaintBackground method like this:
protected override void OnPaintBackground(PaintEventArgs e)
{
//empty implementation
}
(Notice that the base.OnpaintBackground(e) is removed from the function)
Is there any way to make a panel transparent or semi transparent? I haven't found any appropriate property to set transparency for a panel.
I was also trying to make a WPF control with grid (grid background and control background was set to transparent) and place it on normal windows form, but when I put this control on normal Windows Form(not WPF) I don't get the proper transparency.
If your display is pretty much static, you can do this to achieve semi-transparency (Source):
class SeeThroughPanel : Panel
{
public SeeThroughPanel()
{
}
protected override CreateParams CreateParams {
get {
var cp = base.CreateParams;
cp.ExStyle |= 0x00000020;
return cp;
}
}
protected override void OnPaint(PaintEventArgs e)
{
//base.OnPaint(e);
e.Graphics.FillRectangle(new SolidBrush(Color.FromArgb(50, 0, 0, 0)), this.ClientRectangle);
}
}
But, this approach is not without problems if you need dynamic rendering on your semi-transparent control. See this question which I have posted. Hope it gets answered someday.
Unfortunately, transparency is not natively or well supported in WinForms and is difficult to implement yourself.
If you want a transparent panel that allows you to "see through" the form, take a look at this article, which tells you to set both the Panel's TransparencyKey and BackColor to something like Fuscia. With text/other stuff in the panel this effect may not look so good.
If you want a transparent or translucent panel that shows the form below take a look at this SO question.
I would use WPF all the way, if you are able to use it in a form now.
I'm not sure about making the panel semi-transparent, but I know you can use the TransparencyKey property of the form to create completely transparent sections.
For example, set the form's TransparencyKey property to Fuchsia, then set the panel's BackColor to Fuchsia, and it will create a transparent area on the form.
Edit:
Agree with #Callum Rogers about going with WPF. Text directly on the panel shows fringing (see the label in the screenshot). However, if you need to add this quickly to an existing Win Forms app and don't need to show text directly on the panel, it could work for you.
So, I am pretty unfamiliar with windows forms development.
I'm trying to create a "hey I'm busy doing stuff" component that just spins a shape around. I want this control to be transient and draw on top of any other controls. The class inherits directly from Control.
So I have this in the constructor:
SetStyle(ControlStyles.Opaque, true);
and this:
protected override CreateParams CreateParams
{
get
{
CreateParams parms = base.CreateParams;
parms.ExStyle |= 0x20;
return parms;
}
}
Which gets me a control that will draw on top of other controls.
Now my problem is this. I repaint the control a few times a second to give the appearane of a smooth animation. However, I can't figure out how to clear what was drawn in the previous frame. Using e.Graphics.Clear(Color.Transparent) in OnPaint turns the whole control black.
Is there a way to just clear the drawn contents of a control?
I've noticed that Resizing the the control will clear the background.
Things that Don't Work
Overriding OnPaintBackground to do nothing. Or just calling base.OnPaintBackground. Same results.
Okay, I found the solution here:
https://web.archive.org/web/20141227200000/http://bobpowell.net/transcontrols.aspx
The Parent controls actually must be invalidated in order to retain the transparent background.
You may have to override OnPaintBackground that this article presents: http://saftsack.fs.uni-bayreuth.de/~dun3/archives/creating-a-transparent-panel-in-net/108.html
You may also need to Invalidate the control when it needs to be cleared to force OnPaintBackground to be called.