C# 绘制透明按钮

C# 绘制透明按钮,c#,winforms,button,gdi+,C#,Winforms,Button,Gdi+,我正在尝试在C#(.NET3.5SP1)中创建一个透明按钮,以便在我的WinForms应用程序中使用。我已经尽了一切努力使按钮透明(它应该显示按钮下面的渐变背景),但它就是不起作用 以下是我正在使用的代码: public class ImageButton : ButtonBase, IButtonControl { public ImageButton() { this.SetStyle( ControlStyles.SupportsTr

我正在尝试在C#(.NET3.5SP1)中创建一个透明按钮,以便在我的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内存,并用VisualStudio UI中的一些缓冲区(在设计模式下)填充自己。在运行时,它会抓取一些零d缓冲区,并且完全是黑色的

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

有什么想法吗

编辑:谢谢大家,以下内容对我很有用:

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

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

我已经编写了许多透明控件,但我总是从Control或UserControl继承

当您想要阻止控件绘制它的背景时-您应该重写OnPaintBackground而不是OnPaint,并且不调用基类

用画笔填充一个长方形。透明是很有趣的——你正在用一种看不见的颜色在那里画什么。或者换一种说法:它什么也不做

WinForms(以及底层User32)根本不支持透明性。然而,WinForms可以通过使用您提供的控件样式-SupportsTransparentBackColor来模拟透明度,但在本例中,所有“透明”控件都允许绘制其背景


ButtonBase使用了一些阻止使用此机制的windows样式。我看到两种解决方案:一种是从控件派生控件(而不是ButtonBase),第二种是使用父控件的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);...

我知道这个问题很老了,但是如果有人不想创建一个控件来实现这一点,我在另一篇文章中提出了这段代码,并将其更改为一个扩展方法

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

看起来是:该线程中建议的内容对我不起作用。请尝试使用不透明度值为0的新颜色(而不是颜色)进行绘制。透明+1可提供大量信息@arbiter,但某些代码示例肯定会走得更远。这是他所想的,但不是按钮,而是标签。(我想)