Why can\'t I set the BackColor of a Label to Transparent? I have done it before, but now it just don\'t want to...
I created a new UserControl, added a progressbar a
Here is a transparent control I wrote a while ago which displays rotated text. Most of the code comes from here, though IIRC I had to make a few tweaks to get it to work.
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Windows.Forms;
namespace MyNamespace
{
public partial class RotatedText : UserControl
{
private readonly Timer _invalidationTimer;
private const int WS_EX_TRANSPARENT = 0x00000020;
public RotatedText()
{
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
InitializeComponent();
_invalidationTimer = new Timer {Interval = 500, Enabled = true};
_invalidationTimer.Tick += TickHandler;
}
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Category("Appearance")]
[Description("Text which appears in control")]
public string Text { get; set; }
#region Transparent background
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= WS_EX_TRANSPARENT;
return cp;
}
}
private void TickHandler(object sender, EventArgs e)
{
InvalidateEx();
}
private void InvalidateEx()
{
if (Parent != null)
Parent.Invalidate(Bounds, false);
else
Invalidate();
}
protected override void OnPaintBackground(PaintEventArgs e)
{
//Intentionally do nothing - stops background from drawing
//base.OnPaintBackground(e);
}
#endregion
//Rotate text and draw
protected override void OnPaint(PaintEventArgs e)
{
double angleRadians = Math.Atan2(Height, Width);
float angleDegrees = -1*(float) (angleRadians*180/Math.PI);
angleDegrees *= 0.9f;
e.Graphics.RotateTransform(angleDegrees, MatrixOrder.Append);
e.Graphics.TranslateTransform(20, Height - 75, MatrixOrder.Append);
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
Font font = new Font("Ariel", 50);
e.Graphics.DrawString(Text, font, Brushes.Gray, 1, 2); //Shadow
e.Graphics.DrawString(Text, font, Brushes.Red, 0, 0);
}
}
}
WinForms doesn't really support transparent controls, but you can make a transparent control yourself. See my answer here.
In your case you should probably subclass the progress bar and override the OnPaint method to draw a text on the progress bar.
This is a very simple solution and works great:
public class MyLabel : Label
{
private bool fTransparent = false;
public bool Transparent
{
get { return fTransparent; }
set { fTransparent = value; }
}
public MyLabel() : base()
{
}
protected override CreateParams CreateParams
{
get
{
if (fTransparent)
{
CreateParams cp = base.CreateParams;
cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
return cp;
}
else return base.CreateParams;
}
}
protected override void WndProc(ref Message m)
{
if (fTransparent)
{
if (m.Msg != 0x14 /*WM_ERASEBKGND*/ && m.Msg != 0x0F /*WM_PAINT*/)
base.WndProc(ref m);
else
{
if (m.Msg == 0x0F) // WM_PAINT
base.OnPaint(new PaintEventArgs(Graphics.FromHwnd(Handle), ClientRectangle));
DefWndProc(ref m);
}
}
else base.WndProc(ref m);
}
}
When label backcolor is transparent, then label only takes picture of its underlying control the first time when it is created, after that label backcolor is constant. And each time when label repaints itself, it repaints to that fixed color or pattern.
Overriding CreateParams affects on how window for control will be created, this enables real transparency.
Overriding WndProc you control which messages should be passed to base class. We must filtrate WM_ERASEBKGND and WM_PAINT, but we also have to trigger paint event.
as to an explanation for your problem, windows doesn't do transparency for background controls like you'd expect-i'm guessing the gray background is actually the form's surface. whatever controls are drawn between the form surface and your label are ignored.
Use a LinkLabel not a normal Label
private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel)
{
this.MakeTransparentLabel(LinkLabel, Color.White);
}
private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel, Color ForeColor)
{
LinkLabel.ForeColor = ForeColor;
LinkLabel.LinkColor = ForeColor;
LinkLabel.VisitedLinkColor = ForeColor;
LinkLabel.ActiveLinkColor = ForeColor;
LinkLabel.DisabledLinkColor = ForeColor;
LinkLabel.LinkArea = new LinkArea(0, 0);
LinkLabel.LinkBehavior = LinkBehavior.NeverUnderline;
LinkLabel.Cursor = Cursors.Arrow;
LinkLabel.BackColor = Color.Transparent;
}
private void SetTransparentLabelText(System.Windows.Forms.LinkLabel LinkLabel, string Text)
{
if (string.IsNullOrEmpty(Text)) { LinkLabel.Text = " "; return; }
LinkLabel.Text = Text;
}