【问题标题】:Drawing a transparent button绘制透明按钮
【发布时间】:2010-11-08 08:49:35
【问题描述】:

我正在尝试在 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 中的一些缓冲区填充自身(在设计模式下)。在运行时,它会抓取一些零缓冲区并且完全是黑色的。

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

有什么想法吗?

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

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

【问题讨论】:

  • 看起来与以下内容重复:stackoverflow.com/questions/201778/…
  • 该线程中的建议对我不起作用。
  • 尝试使用不透明度值为 0 的新颜色而不是 Color.Transparent 进行绘画

标签: c# winforms button gdi+


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      【解决方案4】:

      我不确定 ButtonBase 是否支持透明度...您检查了吗?

      我写了很多透明控件,但我总是继承自 Control 或 UserControl。

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

      虽然用 Brushes.Transparent 填充矩形很有趣 - 您正在用一种不可见的颜色覆盖那里的区域。或者换一种说法:它什么都不做!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-01-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多