【问题标题】:How can I set the opacity or transparency of a Panel in WinForms?如何在 WinForms 中设置面板的不透明度或透明度?
【发布时间】:2011-05-26 16:32:39
【问题描述】:

我想知道如何在 C# 中更改或修改面板的透明度,而不是整个表单,而只是面板。我看过很多关于不透明度的 C# 教程,但它是针对表单的。我正在寻找如何仅使用面板来实现。谢谢!

【问题讨论】:

    标签: .net winforms transparency panel opacity


    【解决方案1】:

    对于仍在寻找完全透明面板的人,我在this blog by William Smash 中找到了一个不错的解决方案,而后者又从Tobias Hertkorn on his T# blog 中获得了它。我认为值得在这里发布它作为答案。

    C#代码:

    public class TransparentPanel : Panel
    {
        protected override CreateParams CreateParams 
        {            
            get {
                CreateParams cp =  base.CreateParams;
                cp.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
                return cp;
                }
        }
        protected override void OnPaintBackground(PaintEventArgs e) 
        {
            //base.OnPaintBackground(e);
        }
    }
    

    VB.Net 代码:

    Public Class TransparentPanel
    Inherits Panel
        Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
            Get
                Dim cp As CreateParams = MyBase.CreateParams
                cp.ExStyle = cp.ExStyle Or &H20 ''#WS_EX_TRANSPARENT
                Return cp
            End Get
        End Property
        Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
        ''#MyBase.OnPaintBackground(e)
        End Sub
    End Class
    

    【讨论】:

    • 这很好,1个问题:有没有办法给表格加阴影?所以我们目前有一个完全透明的面板,但是我们可以稍微遮蔽它,以便用户可以专注于我们定义的部分吗?
    • 我已将此面板应用到一个表单并在 onPaintBackground 上以不透明颜色绘制剪辑矩形,但在表单下方我有其他控件,即使面板已打开,这些控件似乎也过度绘制了这个新面板表单控件和我的其他自定义控件放在另一个面板上。我是否需要在自定义控件中执行任何特定操作以允许在顶部进行绘图?
    【解决方案2】:

    是的,不透明度只能在顶级窗口上使用。它使用视频适配器的硬件功能,不支持子窗口,如面板。 Winforms 中唯一的顶级 Control 派生类是 Form。

    一些“纯”Winform 控件,它们自己绘制而不是让原生 Windows 控件完成这项工作,但是支持透明背景色。面板就是其中之一。它使用了一个技巧,它要求父级绘制自己以产生背景像素。这个技巧的一个副作用是重叠控件不起作用,您只能看到父像素,而不是重叠的控件。

    这个示例表单展示了它的工作原理:

    public partial class Form1 : Form {
        public Form1() {
            InitializeComponent();
            this.BackColor = Color.White;
            panel1.BackColor = Color.FromArgb(25, Color.Black);
        }
        protected override void OnPaint(PaintEventArgs e) {
            e.Graphics.DrawLine(Pens.Yellow, 0, 0, 100, 100);
        }
    }
    

    如果这还不够好,那么您需要考虑将表单堆叠在一起。 Like this.

    值得注意的是,Windows 8 中取消了此限制。它不再使用视频适配器覆盖功能,并且不能再关闭 DWM(又名 Aero)。这使得子窗口的不透明度/透明度易于实现。依靠这一点当然是未来一段时间的音乐。 Windows 7 将成为下一个 XP :)

    【讨论】:

    • 我已经发布了 Windows 7 和旧 Windows 2003 上的渲染比较stackoverflow.com/a/32075941/1529139
    • 还有在 Win8 和更高版本上。从 MSDN Windows 8:顶级窗口和子窗口支持 WS_EX_LAYERED 样式。以前的 Windows 版本仅支持顶级窗口的 WS_EX_LAYERED。
    【解决方案3】:

    根据在http://www.windows-tech.info/3/53ee08e46d9cb138.php 找到的信息,我能够使用以下代码实现半透明面板控件。

    public class TransparentPanel : Panel
    {
        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.ExStyle |= 0x00000020; // WS_EX_TRANSPARENT
    
                return cp;
            }
        }
    
        protected override void OnPaint(PaintEventArgs e) =>
            e.Graphics.FillRectangle(new SolidBrush(this.BackColor), this.ClientRectangle);
    }
    

    需要注意的是,添加到面板的任何控件都具有不透明的背景。尽管如此,半透明面板对我来说还是有用的,它可以挡住我的 WinForms 应用程序的某些部分,以便将用户的注意力转移到应用程序的适当区域。

    【讨论】:

    • 这对我不起作用。面板是透明的,没有 OnPaint 显示的颜色。你确定这是全班吗?
    • 好吧,我搞定了。但只有当我在面板上完全没有控件时它才有效。面板后面的所有控件仍然正常显示,因此它实际上只是为面板下方的背景着色。这基本上是无用的“覆盖”。
    【解决方案4】:

    不透明面板:

    public class GlassyPanel : Panel
    {
        const int WS_EX_TRANSPARENT = 0x20;  
    
        int opacity = 50;
    
        public int Opacity
        {
            get
            {
                return opacity;
            }
            set
            {
                if (value < 0 || value > 100) throw new ArgumentException("Value must be between 0 and 100");
                opacity = value;
            }
        }
    
        protected override CreateParams CreateParams
        {
            get
            {
                var cp = base.CreateParams;
                cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
    
                return cp;
            }
        }
    
        protected override void OnPaint(PaintEventArgs e)
        {
            using (var b = new SolidBrush(Color.FromArgb(opacity * 255 / 100, BackColor)))
            {
                e.Graphics.FillRectangle(b, ClientRectangle);
            }
    
            base.OnPaint(e);
        }
    }
    

    【讨论】:

      【解决方案5】:

      试试这个:

      panel1.BackColor = Color.FromArgb(100, 88, 44, 55);
      

      更改 alpha(A) 以获得所需的不透明度。

      【讨论】:

      • 对于0-255色的原理图不太熟悉的朋友,可以这样使用:panel1.BackColor = Color.FromArgb(50, Color.Green);
      • 我似乎无法让它工作。更改 alpha 层会使面板的颜色变暗或变亮,但我看不到它后面的控件。我错过了什么吗?
      • 不起作用。请参阅this 答案。
      • 这确实有效!我刚刚使用它,使我的面板在我的初始屏幕上半透明
      【解决方案6】:

      在表单构造函数中动态创建面板时,不要忘记将面板置于最前面。选项卡控件的透明面板覆盖示例。

      panel1 = new TransparentPanel();
      panel1.BackColor = System.Drawing.Color.Transparent;
      panel1.Location = new System.Drawing.Point(0, 0);
      panel1.Name = "panel1";
      panel1.Size = new System.Drawing.Size(717, 92);
      panel1.TabIndex = 0;
      tab2.Controls.Add(panel1);
      panel1.BringToFront(); 
      

      //

      【讨论】:

        【解决方案7】:

        据我所知,面板只能具有透明色,您无法控制面板的不透明度。因此,您可以让面板的某些部分完全透明,但不能让 50% 的内容显示出来。

        要使用透明度,您必须定义透明颜色属性。

        【讨论】:

          【解决方案8】:

          我只是想添加到 William Smash 解决方案中,因为我无法访问他的博客,因此无法找到我简单问题的答案。

          我花了一段时间才意识到,但也许我只是有片刻......

          如果您不需要这样做,则需要在项目属性中添加对 System.Windows.Forms 的引用。

          你还需要添加

          Imports System.Windows.Forms 
          

          到您要添加覆盖类的文件中。

          对于 OnPaintBackground,您需要为 System.Drawing 添加一个引用,然后

          Imports System.Drawing.Printing.PrintEventArgs
          

          【讨论】:

            【解决方案9】:

            有些 cmets 说它有效,有些则说它无效 它仅适用于您的 form 背景而不适用于任何其他 controls 后面

            【讨论】:

              【解决方案10】:

              这对我有用。 在下面的示例中,Alpha 范围可以是 0 到 255 之间的值。 以前,我误以为它必须是百分比值。

              Dim x as integer = 230 Panel1.BackColor = Color.FromArgb(x, Color.Blue)

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 2010-10-25
                • 2014-09-05
                • 2014-07-28
                • 1970-01-01
                • 2016-03-01
                • 1970-01-01
                • 1970-01-01
                • 2016-05-15
                相关资源
                最近更新 更多