为什么我不能将标签的背景颜色设置为透明?我以前做过,但现在它只是不想......
我创建了一个新的 UserControl,添加了一个进度条和一个标签。当我将标签的 BackColor 设置为透明时,它仍然是灰色 =/ 这是为什么?
我想要的是将标签放在进度条顶部,以便其文本在进度条“中”...
为什么我不能将标签的背景颜色设置为透明?我以前做过,但现在它只是不想......
我创建了一个新的 UserControl,添加了一个进度条和一个标签。当我将标签的 BackColor 设置为透明时,它仍然是灰色 =/ 这是为什么?
我想要的是将标签放在进度条顶部,以便其文本在进度条“中”...
向您的项目添加一个新类并发布如下所示的代码。建造。将新控件从工具箱顶部拖放到表单上。
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;
}
}
}
WinForms 并不真正支持透明控件,但是你可以自己制作一个透明控件。在这里查看我的答案。
在您的情况下,您可能应该子类化进度条并覆盖 OnPaint 方法以在进度条上绘制文本。
最简单的解决方案如下:
在可视化编辑器或表单的构造函数中将背景颜色设置为透明度:
this.label1.BackColor = System.Drawing.Color.Transparent;
设置标签的 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;
}
这是一个非常简单的解决方案,效果很好:
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,但我们还必须触发绘制事件。
如果您想专注于设计您的 Windows 应用程序,我建议您使用 WPF。
在 WPF 中使控件透明是非常容易的。
<TextBox Width="200" Height="40" Opacity="0.5"/>
这是我不久前写的一个透明控件,它显示旋转的文本。大部分代码都来自这里,尽管 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);
}
}
}
因此,正如对我之前回答的评论所述,控制是默认行为,并且我记得是透明的。
无论如何,您是否尝试过设置 UserControl 的背景属性或标签所在的容器(面板、表单等?),您的标签应该反映该颜色 :)
旧答案:我已经有一段时间没有进行 winforms 编程了,但我记得标签默认是透明的?因此,它只有获得实际颜色的文本,而免费的颜色模仿它背后的任何东西:)
完全可以做到你想要达到的目标。玩控件只需要一点时间。可以创建一个具有透明背景的 Label 控件,并将其放在 Progressbar 控件的顶部。
检查我对另一个 SO 问题的回答。
至于对您的问题的解释,Windows 不会像您期望的那样对背景控件进行透明度 - 我猜灰色背景实际上是表单的表面。在表单表面和标签之间绘制的任何控件都将被忽略。
选择BackColor,转到 Web 选项卡,然后选择透明。生成以下内容。
this.label1.BackColor = System.Drawing.Color.Transparent;