为什么WinForms标签不希望透明的原因?

为什么我不能将Label的BackColor设置为Transparent? 我以前做过,但现在它只是不想……

我创建了一个新的UserControl,为它添加了一个进度条和一个标签。 当我将标签的BackColor设置为透明时,它仍然是灰色= /为什么这样?

我想要的是将标签放在进度条的顶部,以便其文本“在”进度条中“…

WinForms并不真正支持透明控件,但您可以自己制作透明控件。 在这里看到我的答案 。

在您的情况下,您可能应该inheritance进度条并覆盖OnPaint方法以在进度条上绘制文本。

在项目中添加一个新类并发布下面显示的代码。 建立。 将新控件从工具箱顶部拖放到表单上。

using System; using System.Windows.Forms; public class TransparentLabel : Label { public TransparentLabel() { this.SetStyle(ControlStyles.Opaque, true); this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false); } protected override CreateParams CreateParams { get { CreateParams parms = base.CreateParams; parms.ExStyle |= 0x20; // Turn on WS_EX_TRANSPARENT return parms; } } } 

最简单的解决方案如下:

  1. 在可视化编辑器或表单的构造函数中将背景颜色设置为透明度:

    this.label1.BackColor = System.Drawing.Color.Transparent;

  2. 设置标签的Parent属性以控制您希望在文本后面显示。 这可以在表单构造函数或Load方法中完成:

    this.label1.Parent = progressBar1;

确实,这不像DirectX那样真正的透明度。 您在显示屏上看到的结果仅由两层组成。 您不能使用此方法总结两个以上的图层(每个图层都有自己的透明度由alpha参数定义)。 但它适用于Winforms编程中可能遇到的许多实际情况。

使用LinkLabel而不是普通标签

  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; } 

如果你想专注于设计你的Windows应用程序,我建议你使用WPF。

在WPF中使控制透明非常容易。

  

这是我前一段时间写的透明控件,它显示旋转的文本。 大多数代码来自这里 ,虽然IIRC我不得不做一些调整才能让它工作。

 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); } } } 

这是一个非常简单的解决方案,效果很好:

 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); } } 

当标签背景色是透明的时,标签只会在其创建后第一次拍摄其底层控件的图片,之后标签背景色是常量。 每次标签重新绘制时,它都会重新绘制为固定的颜色或图案。

覆盖CreateParams会影响如何创建控件窗口,这样可以实现真正的透明度。

覆盖WndProc,您可以控制应将哪些消息传递给基类。 我们必须过滤WM_ERASEBKGND和WM_PAINT,但我们还必须触发paint事件。

因此,对我之前的回答所说的评论,Control是默认行为,我记得它是透明的。

无论如何,您是否尝试过设置UserControl的背景属性,或者您的标签所在的容器(面板,表格,等等?),您的标签应该反映出那种颜色:)


旧答案:自从我做了winforms编程以来已经有一段时间了,但我记得标签在默认情况下是透明的吗? 因此它只有获得实际颜色的文本,而bacground颜色模仿它背后的任何东西:)

可以完全按照您想要的方式完成。 使用控件只需要一点时间。 可以创建具有透明背景的Label控件,并将其放在Progressbar控件的顶部。

检查我对另一个SO问题的回答。

至于你的问题的解释,Windows不像你期望的那样为背景控件做透明度 – 我猜测灰色背景实际上就是表格的表面。 在表单表面和标签之间绘制的任何控件都将被忽略。

选择BackColor ,转到Web选项卡,然后选择透明。 生成以下内容。

  this.label1.BackColor = System.Drawing.Color.Transparent;