绘制透明按钮

我正在尝试在C#(.NET 3.5 SP1)中创建一个透明按钮,以便在我的WinForms应用程序中使用。 我已经尝试了一切让按钮变得透明(它应该在按钮下方显示渐变背景)但它只是不起作用。

这是我正在使用的代码:

public class ImageButton : ButtonBase, IButtonControl { public ImageButton() { this.SetStyle( ControlStyles.SupportsTransparentBackColor | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true); this.BackColor = Color.Transparent; } protected override void OnPaint(PaintEventArgs pevent) { Graphics g = pevent.Graphics; g.FillRectangle(Brushes.Transparent, this.ClientRectangle); g.DrawRectangle(Pens.Black, this.ClientRectangle); } // rest of class here... } 

问题是按钮似乎是从某个地方抓取随机UI内存并从Visual Studio的UI中填充一些缓冲区(在设计模式下)。 在运行时它会抓住一些零缓冲区并且完全是黑色的。

我的最终目标是在隐形按钮而不是矩形上绘制图像。 然而,这个概念应该保持不变。 当用户将鼠标hover在按钮上时,则绘制按钮类型的形状。

有任何想法吗?

编辑:谢谢大家,以下为我工作:

 public class ImageButton : Control, IButtonControl { public ImageButton() { SetStyle(ControlStyles.SupportsTransparentBackColor, true); SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.ResizeRedraw, true); this.BackColor = Color.Transparent; } protected override void OnPaint(PaintEventArgs pevent) { Graphics g = pevent.Graphics; g.DrawRectangle(Pens.Black, this.ClientRectangle); } protected override void OnPaintBackground(PaintEventArgs pevent) { // don't call the base class //base.OnPaintBackground(pevent); } protected override CreateParams CreateParams { get { const int WS_EX_TRANSPARENT = 0x20; CreateParams cp = base.CreateParams; cp.ExStyle |= WS_EX_TRANSPARENT; return cp; } } // rest of class here... } 

WinForms(和底层User32)根本不支持透明度。 但是,WinForms可以通过使用你提供的控件样式来模拟透明度 – SupportsTransparentBackColor,但在这种情况下,所有“透明”控件都可以,它允许绘制父级的背景。

ButtonBase使用一些阻止使用此机制的窗口样式。 我看到两个解决方案:一个是从Control(而不是ButtonBase)派生你的控件,第二个是使用Parent的DrawToBitmap来获取你的按钮下的背景,然后在OnPaint中绘制这个图像。

在winforms中有一些技巧可以让控件在使用透明度时正确绘制背景。 您可以将此代码添加到OnPaint或OnPaintBackground以获取您在后台绘制的控件:

 if (this.Parent != null) { GraphicsContainer cstate = pevent.Graphics.BeginContainer(); pevent.Graphics.TranslateTransform(-this.Left, -this.Top); Rectangle clip = pevent.ClipRectangle; clip.Offset(this.Left, this.Top); PaintEventArgs pe = new PaintEventArgs(pevent.Graphics, clip); //paint the container's bg InvokePaintBackground(this.Parent, pe); //paints the container fg InvokePaint(this.Parent, pe); //restores graphics to its original state pevent.Graphics.EndContainer(cstate); } else base.OnPaintBackground(pevent); // or base.OnPaint(pevent);... 

我不确定ButtonBase是否支持透明度……你检查过了吗?

我编写了许多透明控件,但我总是inheritance自Control或UserControl。

当你想阻止控件绘制它的背景时 – 你应该重写OnPaintBackground而不是OnPaint而不是调用基类。

用Brushes.Transparent填充一个矩形很有趣 – 你在那里画的是一种看不见的颜色。 换句话说:它什么都不做!

我知道这个问题很老,但是如果有人不想创建一个控件来执行此操作,我会从另一篇文章中提出这个代码并将其更改为扩展方法。

 public static void ToTransparent(this System.Windows.Forms.Button Button, System.Drawing.Color TransparentColor) { Bitmap bmp = ((Bitmap)Button.Image); bmp.MakeTransparent(TransparentColor); int x = (Button.Width - bmp.Width) / 2; int y = (Button.Height - bmp.Height) / 2; Graphics gr = Button.CreateGraphics(); gr.DrawImage(bmp, x, y); } 

这个电话就像:

 buttonUpdate.ToTransparent(Color.Magenta);