Cmptrb
Cmptrb

Reputation: 255

Transparency issue by Overlapped PictureBox's at C#

I'm displaying in a panel PictureBox overlapped, because each PictureBox is used as a layer. First time a PictureBox is defined and added to panel it's background color is transparent, and it's images are empty.

The problem is, the bottom layer can not be seen, the transparent image, shows the panel's ground. Excepted is that the bottom PictureBox's image is seen.

I have tried to it with other controls like label. The problem could not be solved :(

Thanks.

Upvotes: 5

Views: 17777

Answers (4)

dwidel
dwidel

Reputation: 1294

I've been able to do this in VB. There are a couple of tricks though. First of all you have to add the picture boxes to each other. Second the images in the picture boxes have to be PNGs.

For this app I had to display 3 different layers on top of a background layer and turn them on and off with checkboxes. If it doesn't work, play around with how you save your PNGs, it's kind of picky about that.

Imports System.Drawing
Imports System.Drawing.Imaging
Imports System

Public Class Form1

    Dim MarkerBox1 As New PictureBox
    Dim MarkerBox2 As New PictureBox
    Dim MarkerBox3 As New PictureBox

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        PictureBox1.Image = New Bitmap("C:\BackGround.bmp")

        MarkerBox1.Image = New Bitmap("C:\TestOverlay1.png")
        MarkerBox1.BackColor = System.Drawing.Color.Transparent
        MarkerBox1.Visible = True
        MarkerBox1.SizeMode = PictureBoxSizeMode.AutoSize
        PictureBox1.Controls.Add(MarkerBox1)

        MarkerBox2.Image = New Bitmap("C:\TestOverlay2.png")
        MarkerBox2.BackColor = System.Drawing.Color.Transparent
        MarkerBox2.Visible = True
        MarkerBox2.SizeMode = PictureBoxSizeMode.AutoSize
        MarkerBox1.Controls.Add(MarkerBox2)

        MarkerBox3.Image = New Bitmap("C:\TestOverlay3.png")
        MarkerBox3.BackColor = System.Drawing.Color.Transparent
        MarkerBox3.Visible = True
        MarkerBox3.SizeMode = PictureBoxSizeMode.AutoSize
        MarkerBox2.Controls.Add(MarkerBox3)


    End Sub

    Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
        If CheckBox1.Checked Then
            MarkerBox1.Visible = True
        Else
            MarkerBox1.Visible = False
        End If
        Visibilitychanged()
    End Sub

    Private Sub CheckBox2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox2.CheckedChanged
        If CheckBox2.Checked Then
            MarkerBox2.Visible = True
        Else
            MarkerBox2.Visible = False
        End If
        Visibilitychanged()
    End Sub

    Private Sub CheckBox3_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox3.CheckedChanged
        If CheckBox3.Checked Then
            MarkerBox3.Visible = True
        Else
            MarkerBox3.Visible = False
        End If
        Visibilitychanged()
    End Sub

    Private Sub Visibilitychanged()

        PictureBox1.Controls.Clear()
        MarkerBox1.Controls.Clear()
        MarkerBox2.Controls.Clear()
        MarkerBox3.Controls.Clear()

        Dim PB As PictureBox = PictureBox1
        If MarkerBox1.Visible Then
            PB.Controls.Add(MarkerBox1)
            PB = MarkerBox1
        End If
        If MarkerBox2.Visible Then
            PB.Controls.Add(MarkerBox2)
            PB = MarkerBox2
        End If
        If MarkerBox3.Visible Then
            PB.Controls.Add(MarkerBox3)
            PB = MarkerBox3
        End If

    End Sub

Upvotes: 2

zee
zee

Reputation: 641

You should do

pe.Graphics.DrawImage(Image, 0, 0, Image.Width, Image.Height);

so your Image won't be streched

Upvotes: 0

Rado
Rado

Reputation: 8953

This is my take on it:

class TransPictureBox : Control
{
    private Image _image = null;

    public Image Image
    {
        get
        {
            return _image;
        }
        set
        {
            _image = value;
        }
    }
    public TransPictureBox()
    {
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        if(Image != null)
            pe.Graphics.DrawImage(Image, 0, 0);
    }
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }
}

You should add some more logic for positioning the image as you wish and edit the OnPaint method accordingly.

Upvotes: 6

Sean Hanley
Sean Hanley

Reputation: 5727

This is because, if I remember correctly, setting a background color of Transparent (its actual value is null, right?) isn't really transparent. What Windows does is it looks at the control's parent container's background color and sets the controls background color to that.

You can see this happen especially with panels. Without contents, panels set to Transparent should let you see behind them, right? Wrong. If you put a panel on top of a bunch of, say, textbox controls and set the panel to Transparent, you won't be able to see the textboxes behind it.

Instead, to get real transparency, you have to overload OnPaintBackground for the control in question and, essentially, do absolutely nothing (DONT'T call the base.OnPainBackground either!)... There's more to it than that, probably, but here is an example of a working TransparentPanel control we use here:

public class TransparentPanel : System.Windows.Forms.Panel
{
    [Browsable(false)]
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // Do Nothing
    }
}

We've used this class successfully to create truly transparent panels in past Windows Forms apps. We used it as a hack to fix the "right-click context menu appears on top of button controls" problem.

Upvotes: 13

Related Questions