C# 通过形状最小化绘制透明面板而不为黑色

C# 通过形状最小化绘制透明面板而不为黑色,c#,winforms,panel,transparency,C#,Winforms,Panel,Transparency,我正在用C#在picturebox中的位图上绘制面板。我使用了下面的代码,当我不最小化表单时,这很好。 当我最小化窗体并再次将其最大化为第一个大小时,该类绘制的所有面板都显示黑色背景。 我发现,当我将ControlStyles.不透明更改为“SupportsTransparentBackColor”等其他内容时,问题会得到解决,但面板将不再透明 public class ExtendedPanel : Panel { private const int WS_EX_TRANSPARENT

我正在用C#在picturebox中的位图上绘制面板。我使用了下面的代码,当我不最小化表单时,这很好。 当我最小化窗体并再次将其最大化为第一个大小时,该类绘制的所有面板都显示黑色背景。 我发现,当我将ControlStyles.不透明更改为“SupportsTransparentBackColor”等其他内容时,问题会得到解决,但面板将不再透明

public class ExtendedPanel : Panel
{
    private const int WS_EX_TRANSPARENT = 0x00;
    public ExtendedPanel()
    {
         SetStyle(ControlStyles.Opaque, true);
    }

private int opacity = 1;
[DefaultValue(1)]
public int Opacity
{
    get
    {
        return this.opacity;
    }
    set
    {
        if (value < 0 || value > 100)
            throw new ArgumentException("value must be between 0 and 100");
        this.opacity = value;
    }
}
protected override CreateParams CreateParams
{
    get
    {
        CreateParams cp = base.CreateParams;
        cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
        return cp;
    }
}
protected override void OnPaint(PaintEventArgs e)
{
    using (var brush = new SolidBrush(Color.FromArgb(this.opacity * 1 / 100, this.BackColor)))
    {
        e.Graphics.FillRectangle(brush, this.ClientRectangle);
    }
    base.OnPaint(e);
}
公共类扩展面板:面板
{
私有常量int WS_EX_TRANSPARENT=0x00;
公共扩展面板()
{
SetStyle(ControlStyles.不透明,true);
}
私有整数不透明度=1;
[默认值(1)]
公共整数不透明度
{
得到
{
返回此值。不透明度;
}
设置
{
如果(值<0 | |值>100)
抛出新ArgumentException(“值必须介于0和100之间”);
this.opacity=值;
}
}
受保护的重写CreateParams CreateParams
{
得到
{
CreateParams cp=base.CreateParams;
cp.ExStyle=cp.ExStyle | WS_EX_透明;
返回cp;
}
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
使用(var brush=new SolidBrush(Color.FromArgb(this.opacity*1/100,this.BackColor)))
{
e、 Graphics.FillRectangle(画笔,this.ClientRectangle);
}
基础漆(e);
}
}

已经告诉您,实际上是什么阻止了面板透明度的工作:
WS\u EX\u TRANSPARENT
被设置为
0x00
,而不是
0x20

改善半透明面板外观的一些建议

  • 测试面板设置这些样式
这将防止在设计时和运行时移动面板时面板上出现任何工件

this.SetStyle(ControlStyles.AllPaintingInWmPaint |
              ControlStyles.UserPaint |
              ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
this.DoubleBuffered = false;
this.UpdateStyles();
  • 设置不透明度值时
使用
刷新()。否则,您必须单击表单以查看更改。在运行时,
Invalidate()
就足够了(通常)

set{
如果(值<0 | |值>255)抛出新ArgumentException(“值必须介于0和255之间”);
this.opacity=值;
如果(this.DesignMode)this.FindForm().Refresh();
这个。使无效();
}
修改的测试类:

public class ExtendedPanel : Panel
{
    private const int WS_EX_TRANSPARENT = 0x20;
    public ExtendedPanel()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.UserPaint |
                      ControlStyles.Opaque, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
        this.DoubleBuffered = false;
        this.UpdateStyles();
    }

    private int opacity = 1;

    [DefaultValue(1)]
    public int Opacity
    {
        get => this.opacity;
        set {
            if (value < 0 || value > 255) throw new ArgumentException("value must be between 0 and 255");
            this.opacity = value;
            if (this.DesignMode) this.FindForm().Refresh();
            this.Invalidate();
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
            return cp;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        using (SolidBrush bgbrush = new SolidBrush(Color.FromArgb(this.opacity, this.BackColor)))
        {
            e.Graphics.FillRectangle(bgbrush, this.ClientRectangle);
        }
    }
}
公共类扩展面板:面板
{
私有常量int WS_EX_TRANSPARENT=0x20;
公共扩展面板()
{
此.SetStyle(ControlStyles.AllPaintingInWmPaint|
ControlStyles.UserPaint|
控件样式。不透明,真实);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer,false);
this.DoubleBuffered=false;
this.UpdateStyles();
}
私有整数不透明度=1;
[默认值(1)]
公共整数不透明度
{
get=>this.opacity;
设置{
如果(值<0 | |值>255)抛出新ArgumentException(“值必须介于0和255之间”);
this.opacity=值;
如果(this.DesignMode)this.FindForm().Refresh();
这个。使无效();
}
}
受保护的重写CreateParams CreateParams
{
得到
{
CreateParams cp=base.CreateParams;
cp.ExStyle=cp.ExStyle | WS_EX_透明;
返回cp;
}
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
基础漆(e);
使用(SolidBrush bgbrush=new SolidBrush(Color.FromArgb(this.opacity,this.BackColor)))
{
e、 Graphics.FillRectangle(bgprush,this.ClientRectangle);
}
}
}
已经告诉您,实际上是什么阻止了面板透明度的工作:
WS\u EX\u TRANSPARENT
被设置为
0x00
,而不是
0x20

改善半透明面板外观的一些建议

  • 测试面板设置这些样式
这将防止在设计时和运行时移动面板时面板上出现任何工件

this.SetStyle(ControlStyles.AllPaintingInWmPaint |
              ControlStyles.UserPaint |
              ControlStyles.Opaque, true);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
this.DoubleBuffered = false;
this.UpdateStyles();
  • 设置不透明度值时
使用
刷新()。否则,您必须单击表单以查看更改。在运行时,
Invalidate()
就足够了(通常)

set{
如果(值<0 | |值>255)抛出新ArgumentException(“值必须介于0和255之间”);
this.opacity=值;
如果(this.DesignMode)this.FindForm().Refresh();
这个。使无效();
}
修改的测试类:

public class ExtendedPanel : Panel
{
    private const int WS_EX_TRANSPARENT = 0x20;
    public ExtendedPanel()
    {
        this.SetStyle(ControlStyles.AllPaintingInWmPaint |
                      ControlStyles.UserPaint |
                      ControlStyles.Opaque, true);
        this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
        this.DoubleBuffered = false;
        this.UpdateStyles();
    }

    private int opacity = 1;

    [DefaultValue(1)]
    public int Opacity
    {
        get => this.opacity;
        set {
            if (value < 0 || value > 255) throw new ArgumentException("value must be between 0 and 255");
            this.opacity = value;
            if (this.DesignMode) this.FindForm().Refresh();
            this.Invalidate();
        }
    }

    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
            return cp;
        }
    }

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        using (SolidBrush bgbrush = new SolidBrush(Color.FromArgb(this.opacity, this.BackColor)))
        {
            e.Graphics.FillRectangle(bgbrush, this.ClientRectangle);
        }
    }
}
公共类扩展面板:面板
{
私有常量int WS_EX_TRANSPARENT=0x20;
公共扩展面板()
{
此.SetStyle(ControlStyles.AllPaintingInWmPaint|
ControlStyles.UserPaint|
控件样式。不透明,真实);
this.SetStyle(ControlStyles.OptimizedDoubleBuffer,false);
this.DoubleBuffered=false;
this.UpdateStyles();
}
私有整数不透明度=1;
[默认值(1)]
公共整数不透明度
{
get=>this.opacity;
设置{
如果(值<0 | |值>255)抛出新ArgumentException(“值必须介于0和255之间”);
this.opacity=值;
如果(this.DesignMode)this.FindForm().Refresh();
这个。使无效();
}
}
受保护的重写CreateParams CreateParams
{
得到
{
CreateParams cp=base.CreateParams;
cp.ExStyle=cp.ExStyle | WS_EX_透明;
返回cp;
}
}
受保护的覆盖无效OnPaint(PaintEventArgs e)
{
基础漆(e);
使用