If you need a control support transparency, you should override painting of the control and draw the control in this order:
- Draw all controls in the same container which are under your control (based on z-index) on a bitmap.
- Then draw that bitmap on graphics of your control.
- At last draw content of your control.
- Also the
BackColor
of your control should be Color.Transparent
.
Here is the result of creating TransparentLabel
and TransparentPictureBox
controls. In the below image, there is label, image, label, image and then label in order and as you can see picture boxes and labels has been rendered having transparent background and respecting the z-index:
Transparent Label
class TransparentLabel : Label
{
public TransparentLabel()
{
this.BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
if (Parent != null && this.BackColor == Color.Transparent)
{
using (var bmp = new Bitmap(Parent.Width, Parent.Height))
{
Parent.Controls.Cast<Control>()
.Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this))
.Where(c => c.Bounds.IntersectsWith(this.Bounds))
.OrderByDescending(c => Parent.Controls.GetChildIndex(c))
.ToList()
.ForEach(c => c.DrawToBitmap(bmp, c.Bounds));
e.Graphics.DrawImage(bmp, -Left, -Top);
}
}
base.OnPaint(e);
}
}
Transparent PictureBox
class TransparentPictureBox : PictureBox
{
public TransparentPictureBox()
{
this.BackColor = Color.Transparent;
}
protected override void OnPaint(PaintEventArgs e)
{
if (Parent != null && this.BackColor==Color.Transparent)
{
using (var bmp = new Bitmap(Parent.Width, Parent.Height))
{
Parent.Controls.Cast<Control>()
.Where(c => Parent.Controls.GetChildIndex(c) > Parent.Controls.GetChildIndex(this))
.Where(c => c.Bounds.IntersectsWith(this.Bounds))
.OrderByDescending(c => Parent.Controls.GetChildIndex(c))
.ToList()
.ForEach(c => c.DrawToBitmap(bmp, c.Bounds));
e.Graphics.DrawImage(bmp, -Left, -Top);
}
}
base.OnPaint(e);
}
}