
Creating transparent Windows Forms controls. The transparency
feature of the Windows Forms control leaves much to be desired and is a
blatant fudge. The control is not really transparent, it just pretends to
be by looking at the background of it's parent control and copying the
appropriate portion of the image or background onto it's own surface
during the OnPaintBackground method. This means that a
"transparent" control placed on top of another on the same
parent will in fact obscure the other child controls. Figure 1 shows this
effect in action.
Figure1:
A supposedly transparent Panel The panel control
to the right of the form obscures the PictureBox control and shows only
the background of the parent. In order to make a
truly transparent control we need to do a couple of things. Firstly, it's
necessary to change the behaviour of the window by giving it a
WS_EX_TRANSPARENT style. This is accomplished by overriding the
CreateParams property so that the correct window style is included when
the control is instantiated. The listing below shows this property
override. protected override
CreateParams CreateParams {
get
{
CreateParams cp=base.CreateParams;
cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
return cp;
} } The second thing we
need to do is to invalidate the parent of the control, not the control
itself, whenever we need to update the graphics. This ensures that
whatever is behind the control gets painted before we need to do our own
graphics output. To do this, a routine such as that shown in the following
listing is needed. protected void
InvalidateEx() {
if(Parent==null)
return;
Rectangle rc=new Rectangle(this.Location,this.Size);
Parent.Invalidate(rc,true); } Finally, we need to
ensure that the background draw routine does not mess up the recently
repainted parent-form content by stubbing out the OnPaintBackground
method. protected override
void OnPaintBackground(PaintEventArgs
pevent) {
//do not allow the background to be
painted } Now the control is
ready for the rest of its modification. It is important to note at this
point that transparent controls are not suitable for double buffering
using the standard SetStyle method. The memory bitmap which is provided to
your code has an opaque background and does not allow the carefully
retained parent pixels to show through. To complete this
article, a simple control that does nothing but paint moving ellipses on
its surface is shown in the following listing. using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; namespace transcontroldemo {
/// <summary>
///
Summary description for TransPanel.
/// </summary>
public class
TransPanel : Panel
{
Timer Wriggler=new
Timer();
public TransPanel()
{
//
// TODO: Add
constructor logic here
//
Wriggler.Tick+=new
EventHandler(TickHandler);
this.Wriggler.Interval=500;
this.Wriggler.Enabled=true;
}
protected void
TickHandler(object sender, EventArgs e)
{
this.InvalidateEx();
}
protected override
CreateParams CreateParams
{
get
{
CreateParams cp=base.CreateParams;
cp.ExStyle|=0x00000020; //WS_EX_TRANSPARENT
return
cp;
}
}
protected void
InvalidateEx()
{
if(Parent==null)
return;
Rectangle rc=new
Rectangle(this.Location,this.Size);
Parent.Invalidate(rc,true);
}
protected override
void OnPaintBackground(PaintEventArgs
pevent)
{
//do not allow
the background to be painted
}
Random r=new Random();
protected override
void OnPaint(PaintEventArgs e)
{
int h=this.Height/2;
int w=this.Width/2;
Pen p=new
Pen(Color.Black,2);
int x,y;
for(x=0,y=0;
x<w; x+=w/10, y+=h/10)
{
e.Graphics.DrawEllipse(p,x+r.Next(10)-5,y+r.Next(10)-5,this.Width-(2*x),this.Height-(2*y));
}
p.Dispose();
}
} } Figure 2 shows the
transcontroldemo application in action.
Figure
2: A truly transparent control.
Caveat Derivor.The Panel control used in this example is an ideal candidate for transparency retro-fitting because it adds almost nothing to the functionality of ScrollableControl from which it's derived. Panel does little or no painting itself and does not use the double buffered style internally. Other controls which already make assumptions about the way they will display might not be suitable for this technique. For example, any control that uses double buffering internally will certainly not be suitable and will show up with a black, opaque background. This technique will work well on Control, ScrollableControl Panel and GroupBox and is recommended for those of you that want to create a control more-or-less from scratch. Back
to Bob Powell's Windows Forms Tips and Tricks Copyright
Robert W. Powell 2003. All rights reserved.
|