locked
Transparent pictureBox RRS feed

  • Question

  • Hello. I'm trying to develop a transparent pictureBox. My aim is to use several pictureBoxs all with the same location and size. One will have a loaded image, and this pictureBox won't be transparent. The other pictureBoxs will be transparent. With this transparency I expect to see the solid picturebox and each transparent pictureBox has different drawings that are seen over the solid pictureBox.
    I've been trying several ways to do this but unfortunately with no success. Has anyone has done something similar that can help me?
    Thanks in advance,

    Ricardo

    Monday, July 4, 2005 2:29 PM

Answers

  • Here's the transparent picturebox I created back when I'm working on my company's controls; this control only draw an image to the center of the control and lets the parent draw the rest, this achieve the transparency, hope this helps on your project:



    public class TransparentPictureBox : Control
     {
      private Timer refresher;
      private Image _image = null;

      public TransparentPictureBox()
      {
       refresher = new Timer();
       refresher.Tick += new EventHandler(this.TimerOnTick);
       refresher.Interval = 50;
       refresher.Start();
      }

      protected override CreateParams CreateParams
      {
       get
       {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x20;
        return cp;
       }
      }
     
      protected override void OnMove(EventArgs e)
      {
       base.RecreateHandle();
      }
     
      protected override void OnPaint(PaintEventArgs e)
      {
       if (_image != null)
        e.Graphics.DrawImage(_image, (Width/2)-(_image.Width/2), (Height/2)-(_image.Height/2));
      }

      protected override void OnPaintBackground(PaintEventArgs e)
      {
      }

      private void TimerOnTick(object source, EventArgs e)
      {
       base.RecreateHandle();
       refresher.Stop();
      }

      public Image Image
      {
       get
       {
        return _image;
       }
       set
       {
        _image = value;
        base.RecreateHandle();
       }
      }
     }

     



    I used similar method as Bob Powell's, using a Timer to force handle recreate.

    -chris

    Tuesday, August 9, 2005 7:27 AM
  • This is an interesting problem.

    Unfortunately the way Windows Forms handles transparency doesn't deal with overlapping controls.  Transparency is only one level deep in the parenting chain.

    A possible solution is to use nested parented Panels with their BackgroundIMage set to the layer image and their BackColor set to transparent.  Each layer would br represented by a Panel parented to the Panel representing the previous layer.

     - mike
    Thursday, July 7, 2005 11:13 PM

All replies

  • Hi,

    did I get your point that you want to do many layers of pictures?? so that you get one picture made out of 3 pictures for example??? Ar what do you taget to??
    Monday, July 4, 2005 3:46 PM
  • Hello rgerbig.
    Yes, that is the aim. I load a xpto.jpg image for example. Then I want to draw different things in different layers so I can clear specific draws and not all of then. For example: I draw rectangles in layer 1; draw triangles in layer 2. Now I want to clear all triangles. I only need to clear layer 2.
    So I want to simulate these layers having different transparent picturesBoxs. I don't know if this is the best approach, but is the only I can think of.

    Monday, July 4, 2005 4:06 PM
  • This is an interesting problem.

    Unfortunately the way Windows Forms handles transparency doesn't deal with overlapping controls.  Transparency is only one level deep in the parenting chain.

    A possible solution is to use nested parented Panels with their BackgroundIMage set to the layer image and their BackColor set to transparent.  Each layer would br represented by a Panel parented to the Panel representing the previous layer.

     - mike
    Thursday, July 7, 2005 11:13 PM
  • A better solution is to forget about transparent controls, which don't work well. Instead draw everything in a single control using transparent colors. Then you have complete control.

    Regards,
    Frank Hileman
    www.vgdotnet.com
    Friday, July 8, 2005 6:57 PM
  •  Ricardo Tomé wrote:

    Hello. I'm trying to develop a transparent pictureBox. My aim is to use several pictureBoxs all with the same location and size. One will have a loaded image, and this pictureBox won't be transparent. The other pictureBoxs will be transparent. With this transparency I expect to see the solid picturebox and each transparent pictureBox has different drawings that are seen over the solid pictureBox.
    I've been trying several ways to do this but unfortunately with no success. Has anyone has done something similar that can help me?
    Thanks in advance,

    Ricardo




    Hi,

    If by your meaning of "developed" PictureBox is a CustomControl derived from PictureBox control (or any other ScrollableControls), you can achieve true transparency by altering the way it was handled by the parent control;

    1. Add the flag WS_EX_TRANSPARENT to the style of your Control. You can do that by overriding the CreateParams method:

    protected override CreateParams CreateParams
    {
      get
      {
         CreateParams cp = base.CreateParams;
         cp.Style |= 0x20; // WS_EX_TRANSPARENT
         return cp;
      }
    }


    2. Next, prevent your control from drawing the background; can be achieved by overriding the OnPaintBackground method, and leave it blank (not calling the base's OnPaintBackground will suppress the background drawing):

    protected override void OnPaintBackground(PaintEventArgs e)
    {
    }


    3. Finally, you have to call the RecreateHandle for many of your control's changes in size and location, so windows will provide your control the necessary background for your control to be drawn, I do this on the OnMove and OnSizeChanged overriden methods:

    protected override void OnMove(EventArgs e)
    {
     base.OnMove(e);
     RecreateHandle();
    }


    protected override void OnSizeChanged(EventArgs e)
    {
      RecreateHandle();
    }



    Best regards,

    -chris

    Saturday, July 9, 2005 2:07 AM
  • gwapo, I tried to do what you suggested but was unsuccessful. Could you please tell me what I'm doing wrong? I included the CreateParams, OnPaintBackground, and OnMove (don't need OnSizeChanged) methods, then I added an eventhandler to my pictureBox:

    myPicBox.LocationChanged += new EventHandler(OnMove);

    I get an error with the OnMove method:
    Error 1 No overload for 'OnMove' matches delegate.

    Thanks.

    If it makes a difference, I am using an array of pictureboxes, so I'n not using the designer.

    Tuesday, August 9, 2005 6:21 AM
  • Hi,

    On CreateParams, I think I got some mistake:

    cp.Style |= 0x20; should be cp.ExStyle |= 0x20;

    And this method only works by working with RecreateHandle (inside OnMove) or forcing the parent to repaint the part where the transparent control is located.

    Bob Powell's Winforms Tips and Tricks demonstrate the trick of forcing a repaint on parent to achieve transparency:
    http://www.bobpowell.net/transcontrols.htm

    If this still didn't worked, I suggest you to try BitmapRegioning for your game-sprites, by removing the extra part of your control (showing only the region where there is a picture):
    http://www.codeproject.com/csharp/bmprgnform.asp


    -chris
    Tuesday, August 9, 2005 6:54 AM
  • Here's the transparent picturebox I created back when I'm working on my company's controls; this control only draw an image to the center of the control and lets the parent draw the rest, this achieve the transparency, hope this helps on your project:



    public class TransparentPictureBox : Control
     {
      private Timer refresher;
      private Image _image = null;

      public TransparentPictureBox()
      {
       refresher = new Timer();
       refresher.Tick += new EventHandler(this.TimerOnTick);
       refresher.Interval = 50;
       refresher.Start();
      }

      protected override CreateParams CreateParams
      {
       get
       {
        CreateParams cp = base.CreateParams;
        cp.ExStyle |= 0x20;
        return cp;
       }
      }
     
      protected override void OnMove(EventArgs e)
      {
       base.RecreateHandle();
      }
     
      protected override void OnPaint(PaintEventArgs e)
      {
       if (_image != null)
        e.Graphics.DrawImage(_image, (Width/2)-(_image.Width/2), (Height/2)-(_image.Height/2));
      }

      protected override void OnPaintBackground(PaintEventArgs e)
      {
      }

      private void TimerOnTick(object source, EventArgs e)
      {
       base.RecreateHandle();
       refresher.Stop();
      }

      public Image Image
      {
       get
       {
        return _image;
       }
       set
       {
        _image = value;
        base.RecreateHandle();
       }
      }
     }

     



    I used similar method as Bob Powell's, using a Timer to force handle recreate.

    -chris

    Tuesday, August 9, 2005 7:27 AM
  • Thanks, that should help a lot. Actually, I trying to redesign my app to paint the images directly on the main panel background rather than using an array of picture boxes, then even if I still use boxes for animation the transparency will work. (My Tetris game was using 700+MB of memory!) But your example should help me figure out how to do that as well. It will be more complicated, having to calulate coordinates, etc, rather than using box numbers, but the end results will be much better.
    Sunday, August 14, 2005 6:36 PM
  • Hi Chris,
        I am trying to create a Transparent Picture box as well.  Instead of inheriting from Control, I inherited from Picturebox.  I follow the same steps as you, overriding the functions and adding the timer....but I still have a problem.
        If I override the OnPaintBackground of the picture box, the background is not transparent, its solid black.  Have you encountered this at all?  I have made a transparent panel using the same steps and it works fine.  Is it something specific with the Picturebox control?

    Thanks,

    Neil
    Thursday, August 25, 2005 11:59 AM
  • Hi nfedin,

    PictureBox has many background features including support for animation that maybe the reason for causing this hard color background (not sure about this).

    This is also the same reason why I hadn't derived my TransparentPictureBox from PictureBox control.


    -chris
    Friday, August 26, 2005 3:00 AM
  • Hi Gwapo,

     

    I have one more problem in you example,

     

    When i am trying to add the form dynamicly it is not adding, can you tel me the reason for it.

     

    I am writing the following code

     

    Dim pic1 As New TransparentPictureBox

     

    Me.Controls.Add(pic1)

    pic1.Image = Image.FromFile("C:\jpg1.jpg")

     

     

    Regards

     

    vikas

    Tuesday, July 31, 2007 12:38 PM
  • There is an easy way to achieve this, each layer is a picturebox that is added to the previous layer:

    PictureBox Layer1 = new PictureBox();
    PictureBox Layer2 = new PictureBox();
    this.Controls.Add(Layer1);
    Layer2.BackColor = Color.Transparent;
    Layer1.Controls.Add(Layer2);

    The actual graphics are bitmap images drawn on using:

    Graphics g = Grephics.FromImage(theBitmap);
    g.Clear(Color.Transparent);

    Simple multi layer transparency. Just have to manually create the pictureboxes.

    I realise this post was ancient, but I've been trying to do this recently and this is high on Google.
    • Proposed as answer by nott3hmun Friday, July 31, 2009 9:13 PM
    • Edited by nott3hmun Friday, July 31, 2009 9:15 PM
    Friday, July 31, 2009 9:12 PM
  • Thanks Chris, great solution.

    Regards,
    Darrin
    Thursday, March 4, 2010 9:34 AM
  • I have tested your solution, And think that is the best, thanks :D
    Wednesday, April 27, 2011 1:48 AM