1

I have a transparent image that I have made in Photoshop which has a 30% opacity to it.

Now I am trying to put that as background image for a panel. But an ordinary panel even if putting the background color to transparent, shows a white/control background. The panel doesn't become transparent.

So I have found the TransparentPanel class. But when I use that panel, I can't see the image that I put in the code?

I know I can put the background color of the panel to the same as the parent. But that will not work in this case, as the panel is on top of a video control where images are moving underneath.

So I need a completely transparent control that can show the image. I am not sure if this TransparentPanel can be used?

void addpanel()
{
    TransparentPanel tp = new TransparentPanel();
    //Panel tp = new Panel();
    tp.BackColor = Color.Transparent; //This doesn't work?
    tp.BackgroundImage = Properties.Resources.arrowup; //This image is a 30% transparent image (opacity 30%)
    tp.Size = new System.Drawing.Size(54, 54);
    tp.Location = new Point(20, 20);
    panel219.Controls.Add(tp);
    tp.BringToFront();
}
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);
    }
}

EDIT

I have tried this approach also. But still the image in the panel has the color of the CONTROL color which is almost white. One should see through the image that I have since it is 30% opacity?

void addpanel()
{
    TransparentPanel tp = new TransparentPanel(Properties.Resources.arrowup);
    tp.BackColor = Color.Transparent; //This doesn't work?
    tp.Size = new System.Drawing.Size(54, 54);
    tp.Location = new Point(20, 20);
    panel219.Controls.Add(tp);
    tp.BringToFront();
}

class TransparentPanel : Panel
{
    public Image image { get; set; }

    public TransparentPanel(Image img)
    {
        image = img;
        SetStyle(ControlStyles.AllPaintingInWmPaint |
            ControlStyles.OptimizedDoubleBuffer |
            ControlStyles.ResizeRedraw |
            ControlStyles.SupportsTransparentBackColor |
            ControlStyles.UserPaint, true);
        UpdateStyles();
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        //base.OnPaintBackground(pevent);
    }

    protected override void OnPaint(PaintEventArgs pevent)
    {
        base.OnPaint(pevent);

        var g = pevent.Graphics;

        if (Parent != null)
        {
            Rectangle rect = new Rectangle(Left, Top, Width, Height);

            g.TranslateTransform(-rect.X, -rect.Y);

            try
            {
                using (PaintEventArgs pea =
                            new PaintEventArgs(g, rect))
                {
                    pea.Graphics.SetClip(rect);
                    InvokePaintBackground(Parent, pea);
                    InvokePaint(Parent, pea);
                }
            }
            finally
            {
                g.TranslateTransform(rect.X, rect.Y);
            }
        }

        if (image != null)
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            var rectSrc = new Rectangle(0, 0, image.Width, image.Height);
            var rectDes = new Rectangle(0, 0, Width, Height);

            //if (State == MouseState.Over)
                rectDes.Inflate(2, 2);

            g.DrawImage(image, rectDes, rectSrc, GraphicsUnit.Pixel);
        }
    }
}
Peter Duniho
  • 68,759
  • 7
  • 102
  • 136
Andreas
  • 1,121
  • 4
  • 17
  • 34
  • Try taking a look at this: https://stackoverflow.com/questions/2722319/how-to-create-transparent-panel-in-c-net – Jaskier Nov 19 '19 at 19:37
  • Thanks, I tried this in the post: `panel1.BackColor = Color.FromArgb(0, 0, 0, 0);` but that is the same result as: `panel1.BackColor = Color.Transparent;`. The panel doesn't become truly transparent. It seems that the panel has a CONTROL backcolor anyway which is almost white – Andreas Nov 19 '19 at 19:49
  • I tried your approach @JQSOFT in your link. But still the panel doesn't seem transparent? I edited my post with this new code. – Andreas Nov 19 '19 at 23:13
  • I am not sure what I removed? Do you mean something here where the styles are located? `public TransparentPanel(Image img)` I did put them as in your post I think? – Andreas Nov 19 '19 at 23:36
  • `tp.BackgroundImage = Properties.Resources.arrowup;`? You mean tp.Image = Properties.Resources.arrowup;? Also, what is the format of your image? png, jpeg, ..etc. better to screenshot your form to see what's happening. –  Nov 19 '19 at 23:47
  • I only put the image as you have shown in the `TransparentPanel` class. I wrote an answer on your answer below. The panel is working. It is some other logic in my application that is the problem. So thank you very much for your help again! – Andreas Nov 20 '19 at 00:05
  • 1
    Setting `ControlStyles.Opaque`, the Control's Background won't be painted. The you can paint whatever you want in the Paint event event. Something like [this](https://stackoverflow.com/a/51435842/7444103) – Jimi Nov 20 '19 at 02:06
  • @Jimi I need this too `this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true)` (-^_^-) –  Nov 20 '19 at 05:10
  • 1
    @JQSOFT Not sure for you're referring to. If you're talking about transparency/translucency, double buffering doesn't get along with it. If you need a form of buffering, in this case you can use the [BufferedGraphics](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.bufferedgraphics) class directly and implement a custom one. – Jimi Nov 20 '19 at 05:24
  • 1
    @JQSOFT In the sample code I linked, you can see it's disabled (`this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);`). The control won't work correctly using the default implementation. The real custom control from which that code derives, uses its own BufferedGraphics object. – Jimi Nov 20 '19 at 05:33
  • @Jimi Just making noise to say good morning. Not going to argue with someone I learn from him. Your solution is working perfectly and as I commented there, I copied it for further reading. –  Nov 20 '19 at 05:41
  • @JQSOFT All right, thanks by the way. I wasn't sure what the comment was about, so I wrote something related that might be useful, to whomever reads it :) Anyway, double buffering is ok if you paint semi-transparent bitmaps. Maybe you have noticed, that code never paints the background, just some anti-aliased content. In this case, if you enable the default buffering, you'll probably get a *black* background. Without it, you can overlap other controls (more than one at the time) without parenting the transparent control. It won't work with scrolling controls. The code gets more complicated. – Jimi Nov 20 '19 at 05:50

2 Answers2

2

Should be like this:

public class TransparentPanel : Panel
{

    public TransparentPanel()
    {
        SetStyle(ControlStyles.AllPaintingInWmPaint |
            ControlStyles.OptimizedDoubleBuffer |
            ControlStyles.ResizeRedraw |
            ControlStyles.SupportsTransparentBackColor |
            ControlStyles.UserPaint, true);
        UpdateStyles();
    }

    public TransparentPanel(Image img) : this()
    {
        image = img;
    }

    public Image image { get; set; }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
        //base.OnPaintBackground(pevent);
    }

    protected override void OnPaint(PaintEventArgs pevent)
    {
        base.OnPaint(pevent);

        var g = pevent.Graphics;

        if (Parent != null)
        {
            Rectangle rect = new Rectangle(Left, Top, Width, Height);

            g.TranslateTransform(-rect.X, -rect.Y);

            try
            {
                using (PaintEventArgs pea =
                            new PaintEventArgs(g, rect))
                {
                    pea.Graphics.SetClip(rect);
                    InvokePaintBackground(Parent, pea);
                    InvokePaint(Parent, pea);
                }
            }
            finally
            {
                g.TranslateTransform(rect.X, rect.Y);
            }
        }

        if (image != null)
        {
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            var rectSrc = new Rectangle(0, 0, image.Width, image.Height);
            var rectDes = new Rectangle(0, 0, Width, Height);

            //if (State == MouseState.Over)
            rectDes.Inflate(2, 2);

            g.DrawImage(image, rectDes, rectSrc, GraphicsUnit.Pixel);
        }
    }
}
  • Yes I understand thank you. But still, I tried your code and the panel seem to still not be transparent. I start wondering if my image really is transparent. But when looking at the image in photoshop, half of the image is 100% transparent and I save it from there as a .PNG which should work and not replace the transparency with white color as I understand. I have done that many times before. Should the panel be transparent now? – Andreas Nov 19 '19 at 23:46
  • I actually tried with transparent images that I could download from a website that specialize with transparent .png images. I tried with such image with the same result so I can confirm that it is not the image that is the problem. – Andreas Nov 19 '19 at 23:54
  • 1
    Also try `this.Controls.Add(tp)` instead of `panel219.Controls.Add(tp)` for now. –  Nov 19 '19 at 23:54
  • I created a new application because mine are quite complicated and I worry if something else is the problem. In the new application it actually does work. Both with `this.Controls.Add(tp)` and `panel219.Controls.Add(tp)`. So I have to try to figure out what is causing the problem my taking one part away after the other until I can find the solution. I thank you very much for your help and the help with this panel. Thank you again! – Andreas Nov 20 '19 at 00:02
  • Most welcome my friend. uhhh finally, now excuse me I'll go to my room and cry :) –  Nov 20 '19 at 00:11
  • Yes thank you very much. I did find out the problem now. I had 1 panel under the panel219 which I had put to `Color.Tansparent`. When I changed that panel to black then everything works perfect! No please don't cry you were right all the time ;) Just me and the ghost panel under this one whom were the problem ;) – Andreas Nov 20 '19 at 00:16
0

You can use:

TableLayoutPanel tlp = new TableLayoutPanel(); 
tlp.BackColor = Color.FromArgb(150,0,0,0);

That should do the trick. This works and appears transparent.

cigien
  • 57,834
  • 11
  • 73
  • 112
Jules
  • 1