10

I recently started exploring Visual Studio. I was trying to create a slide menu. More specifically, when the user would press the button a submenu would pop up to the right. To achieve that i have placed a Panel to resize itself. Apart from functionality i wanted to add a bit more design and make the Panel appear a bit faded.

I know that Panels in Visual studio do not have opacity, but i was thinking if anyone knows a way-trick-idea about how it can be achieved. I tried a Picture Box but that too didn't have Opacity as a property. I avoided to use the regular Menuobject that visual studio offers because i wanted to add more design. Any ideas?

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
Lio Chon
  • 151
  • 1
  • 2
  • 6
  • possible duplicate of [How can I set the opacity or transparency of a Panel in WinForms?](http://stackoverflow.com/questions/4463363/how-can-i-set-the-opacity-or-transparency-of-a-panel-in-winforms) – Sebastian Negraszus Sep 04 '15 at 14:25
  • I have seen this, but this didn't work for me, that's why i asked. Thx – Lio Chon Sep 04 '15 at 14:35
  • 2
    I don't think it's a duplicate. The poster knows that there is no opacity for controls. – György Kőszeg Sep 04 '15 at 14:35
  • Just what shall be below the Panel or whatever control you will use? What shall shine through? Other Controls? Dynamic content? – TaW Sep 04 '15 at 14:41

3 Answers3

29
  1. Create a class that inherits from Panel.
  2. Set the ControlStyle.Opaque for control in constructor using SetStyle.

If true, the control is drawn opaque and the background is not painted.

  1. Override CreateParams and set WS_EX_TRANSPARENT style for it.

Specifies that a window created with this style is to be transparent. That is, any windows that are beneath the window are not obscured by the window. A window created with this style receives WM_PAINT messages only after all sibling windows beneath it have been updated.

  1. Create an Opacity property that accepts values from 0 to 100 that will be used as alpha channel of background.
  2. Override OnPaint and fill the background using an alpha enabled Brush that is created from BackGroundColor and Opacity.

Complete Code

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

Screenshot

enter image description here

Reza Aghaei
  • 120,393
  • 18
  • 203
  • 398
  • Nice solution. I implemented it with a timer so the opacity would start at 100 and go down to 0. However it is flickering like crazy. Any idea how to get a smooth animation? – ChrisB Sep 22 '16 at 21:03
  • 1
    @ChrisB I'll check it using a timer, but maybe you find [this post](http://stackoverflow.com/a/34338985/3110834) useful. – Reza Aghaei Sep 22 '16 at 21:11
  • @ChrisB By the way, I used [this solution](http://stackoverflow.com/a/39068779/3110834) for a case which I needed a semi-transparent overlay in windows forms. (It may sounds irrelevant, but using a Form as an overlay is a more reliable solution in some cases.) – Reza Aghaei Sep 22 '16 at 21:13
  • 2
    This doesn't seem to work above a `SplitPanel` unfortunately. – user276648 Aug 04 '17 at 09:15
  • 1
    Works in general, but when I put the cursor over the not-overlayed part of the "button on form", the button is brought into the foreground and stays there. How can I fix that? It should return into the background automatically when then mouse leaves it. – Tobias Knauss Jan 26 '18 at 11:48
  • @TobiasKnauss That's why I included the picture. I'll take another look at it to find out if there is a workaround or not. – Reza Aghaei Jan 26 '18 at 12:51
  • 1
    I can't get this to work when I run the app, It displays in the design view, but not when I run the application? – Chud37 Oct 08 '18 at 13:57
  • Just want to add a few notes about using the above code block. 1) Any control behind that is foregrounded needs manually backgrounded and may require a Form.Refresh(); to force a repaint of the form and all its children. – shooky Nov 16 '19 at 17:51
3

To make a control "transparent", you should paint the right area of its parent onto the control. That's what the Button does before it draws its content so the rounded corners will be transparent.

To mimic semi-transparency, you can paint the form onto the panel, and then draw something with 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);
}

Semi-transparent panel

Please note that the ButtonRenderer.DrawParentBackground does not paint the controls of the form, which overlap with the panel, but only the background of the form.

György Kőszeg
  • 17,093
  • 6
  • 37
  • 65
  • If there are controls to be overlapped you can still get the target in a bitmap with drawtobitmap. The animation will look like shite in winforms, though.. – TaW Sep 04 '15 at 15:00
0

Set any color at the panel. For example, black, after which you just need to register the TransparencyKey shape and select the color you want to make transparent:

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