绘制透明按钮

rei*_*ein 21 c# gdi+ button winforms

我正在尝试在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...

}
Run Code Online (Sandbox Code Playgroud)

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

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

有任何想法吗?

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

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...
}
Run Code Online (Sandbox Code Playgroud)

arb*_*ter 16

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

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


jms*_*era 10

在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);...
Run Code Online (Sandbox Code Playgroud)