在Visual Studio窗体中,有没有使用面板的不透明度的技巧?

10

我最近开始探索Visual Studio。我试图创建一个滑动菜单。更具体地说,当用户按下按钮时,子菜单会弹出到右侧。为了实现这一点,我放置了一个Panel来调整大小。除了功能外,我想添加一些设计元素,使Panel看起来有点模糊。

我知道在Visual Studio中的Panels没有不透明度,但我想知道是否有人知道一种方法-技巧-想法如何实现它。我尝试使用Picture Box,但那也没有不透明度属性。我避免使用Visual studio提供的常规Menu对象,因为我想添加更多的设计元素。有任何想法吗?


可能是如何在WinForms中设置Panel的不透明度或透明度?的重复问题。 - Sebastian Negraszus
我看过这个,但对我没有用,所以才问的。谢谢。 - Lio Chon
2
我不认为这是重复的。发帖者知道控件没有不透明度。 - György Kőszeg
面板或者你将要使用的控件下方应该放置什么?是其他控件还是动态内容?需要透过显示吗? - TaW
3个回答

30
  1. 创建一个继承自Panel的类。
  2. 在构造函数中使用SetStyle将控件的ControlStyle.Opaque设置为true。

如果为 true,则绘制不透明控件并且不会绘制背景。

  1. 重写CreateParams,并为其设置WS_EX_TRANSPARENT样式。

指定使用此样式创建的窗口是透明的。也就是说,该窗口下面的任何窗口都不会被该窗口遮挡。使用该样式创建的窗口只有在其下面的所有兄弟窗口更新后才会收到WM_PAINT消息。

  1. 创建一个接受0到100值的Opacity属性,它将用作背景的alpha通道。
  2. 重写OnPaint并使用从BackGroundColorOpacity创建的启用alpha的Brush填充背景。

完整代码

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

    private int opacity = 50;
    [DefaultValue(50)]
    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 * 255 / 100, this.BackColor)))
        {
            e.Graphics.FillRectangle(brush, this.ClientRectangle);
        }
        base.OnPaint(e);
    }
}

屏幕截图

在此输入图片描述


1
@ChrisB 我会使用计时器来检查它,但是也许你会发现这篇帖子有用:https://dev59.com/HpLea4cB1Zd3GeqPyys6#34338985。 - Reza Aghaei
2
很不幸,这似乎在SplitPanel上面无法正常工作。 - user276648
1
一般情况下可以正常工作,但当我将光标放在“表单上的按钮”的非覆盖部分时,按钮会被带到前景并停留在那里。我该如何解决这个问题?当鼠标离开它时,它应该自动返回到后台。 - Tobias Knauss
@TobiasKnauss 这就是为什么我包含了这张图片。我会再看一下,看看是否有解决方法。 - Reza Aghaei
1
当我运行应用程序时,它无法正常工作。在设计视图中可以显示,但在运行应用程序时却不能显示? - Chud37
显示剩余3条评论

3

要使控件“透明”,您应该在其父控件的正确区域上绘制。这就是Button在绘制其内容之前所做的,因此圆角将是透明的。

要模拟半透明效果,您可以将窗体绘制到面板上,然后使用Alpha绘制一些内容:

private void panel1_Paint(object sender, PaintEventArgs e)
{
    PaintTransparentBackground(panel1, e);
    using (Brush b = new SolidBrush(Color.FromArgb(128, panel1.BackColor)))
    {
        e.Graphics.FillRectangle(b, e.ClipRectangle);
    }
}

private static void PaintTransparentBackground(Control c, PaintEventArgs e)
{
    if (c.Parent == null || !Application.RenderWithVisualStyles)
        return;

    ButtonRenderer.DrawParentBackground(e.Graphics, c.ClientRectangle, c);
}

请注意,ButtonRenderer.DrawParentBackground 不会绘制与面板重叠的表单控件,而只会绘制表单的背景。

半透明面板


如果控件重叠,您仍可以使用DrawToBitmap将目标获取为位图。但是,在WinForms中动画效果会很差。 - TaW

0

在面板上设置任何颜色。例如,黑色,之后您只需要注册TransparencyKey形状并选择要使其透明的颜色:

 public Form1()
        {
            InitializeComponent();
            panel1.BackColor = Color.Black; 
            this.TransparencyKey = Color.Black;
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接