Link to home
Start Free TrialLog in
Avatar of Cyber-Drugs
Cyber-DrugsFlag for United Kingdom of Great Britain and Northern Ireland

asked on

C# - Duplicating PNG Picturebox - problem carrying over transparency to new image

Hey guys 'n gals,

I need some help with some code...

I have some code which allows me to duplicate an image, which works almost perfectly...

The source image is a PNG (contains transparency)
The newly cloned image does not carry over this transparency, and replaces the transparent areas with white.


Anybody come across this before? Any thoughts on how to fix this? I am more than happy to give an example of the code, if nobody else has this problem.


Cheers!
Avatar of Yttribium
Yttribium

If you could show me what you've done, then I can see if I can do anything.
In the mean time, I did this:
             Image i = Image.FromFile(@"C:\test.png");
                  PictureBox p = new PictureBox();
                  p.Width = 200;
                  p.Height = 200;
                  p.Top = 205;
                  p.Left = 205;
                  p.Image = (Image)i.Clone();

                  PictureBox p2 = new PictureBox();
                  p2.Image = (Image)p.Image.Clone();
                  p2.Width = 200;
                  p2.Height = 200;
                  p2.Left = 0;
                  p2.Top = 0;

                  p2.Image.Save(@"c:\ta.png");
                  
                  panel2.Controls.Add(p);
                  panel2.Controls.Add(p2);

Both the clone displayed on the panel and saved had the transparency preserved.

So they both worked fine, so I'm very curious what the problem is, unless I misunderstood your question.
Avatar of Cyber-Drugs

ASKER

Sorry for the delayed reply...

You understood my question perfectly and it seems you are using a slightly different method for duplicating the images than me, here is the method I am using:

        void ctl_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                startX = e.X;
                startY = e.Y;
                PictureBox source = (PictureBox)sender;
                pb = new PictureBox();
                pb.Size = source.Size;
                pb.Location = this.PointToClient(panel2.PointToScreen(source.Location));
                pb.Image = source.Image;
                this.Controls.Add(pb);
                pb.BringToFront();
            }
        }



As you can see, I am referencing the image in a slightly different way to you. Hopefully you can see the issue and help me rectify it, it's nothing deadly serious as this is a personal project, but would be good to know how to rectify.


Cheers!
I'm not losing transparency at all... I'm a bit surprised.  Maybe you can send me your project zipped up, I can take a look.  Because I don't get the transparency problem at all.

 If you show me the link to your project when you've uploaded it, I'll try compile and run and see if I get the same problem.  It maybe context dependent.
Sure thing, here it is:

http://ww.cyber-lane.com/CartoLogix.zip

Basically, drag and drop images from the right hand panel to the middle area. While they are being dragged, the transparency is hidden... After they have been dragged and left on top of other images, the transparency is hidden...

I have left a temporary login to the MySQL database so that you can see it working, but you possibly will need the MySQL DLL, if so, here is the one I'm using:


http://www.cyber-lane.com/MySql.Data.dll


Thanks yet again!
By the way, if you are any good with treeViews, I have a question open at the moment which has had 2 replies but they haven't actually solved the problem as of yet, in case you may be interested? I also, have a DataGridView one with pretty much the same.
Can't connect unfortunately, ACCESS DENIED  =/
Ah yeah, sorry forgot...

Can you possibly email your IP address to me so I can grant access: developer@cyber-lane.com
done *waits* hehe
Problem is a little more complex now, the PictureBox in which the image is dispalyed, is NOT transparent (even if BackColor = Color.Transparent) it isn't.  The png images indeed ARE transparent (to the picturebox background)   I'll have to think about this problem now, it's a little more tricky with this issue.  How badly does it have to be "free-form" placement?  Are there other alternative ways of displaying the images on the middle panel?  It would be pretty easy say to put them into a large-icon ListView for instance.

 These are just options for you to consider.
Here is a solution:

//from some MSDN Forum I found a while back
      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();
                  }
            }
      }

Add this class to your program, replace all mentions of PictureBox with TransparentPictureBox.
You will need to comment out some of the properties that are not implemented, and if you need them, find a way to implement them.  But this worked nicely, I've checked that.

Thanks goes to the guy that wrote this thing (somewhere down the thread)
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=53191&SiteID=1
Hey, looks like a good solution, but I got the following errors (due to 2 properties not being available)

Error      1      'CartoLogix.TransparentPictureBox' does not contain a definition for 'BorderStyle'      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      130      28      CartoLogix
Error      2      'CartoLogix.TransparentPictureBox' does not contain a definition for 'BorderStyle'      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      216      32      CartoLogix
Error      3      'CartoLogix.TransparentPictureBox' does not contain a definition for 'BorderStyle'      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      222      28      CartoLogix
Error      4      'CartoLogix.TransparentPictureBox' does not contain a definition for 'SizeMode'      C:\Documents and Settings\Justin Nel\My Documents\Visual Studio 2005\Projects\CartoLogix\CartoLogix\Form1.cs      330      20      CartoLogix


Would it be difficult to manually add 'BorderStyle' and 'SizeMode' to this class?


Thanks again, and Happy Easter!!!
ASKER CERTIFIED SOLUTION
Avatar of Yttribium
Yttribium

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The size mode would take a bit too much time (at least I can't think of anything immediately), but I think you can probably figure it out, you just modify the paint place where I placed the border and do some calculations on the image placement and size.
Thank you yet again for taking all the time you did to help me with this issue!!!

After checking it out, I don't really need the SizeMode property, as I merely wanted to set the image to stretch with the size of it's container, and this seems to do that already.



Thank you!!

At this rate, won't be too long before you get an Expert Ranking in C#! ;o)
Oh no, wait... the drag and drop function isn't working and the images are not resized correctly...

Resizing I'm sure I can fix, but the drag and drop....
What happened?  Drag and drop still works for me I think... what do you mean - it doesn't work? :s
Maybe I've done something wrong?


It compiles fine... Here's the updated code:


http://www.cyber-lane.com/CartoLogix.zip
Took me a few minutes to pin point ONE line of code...

I saw that none of your events were attaching, and it all boiled down to your adding the events ctl_...
foreach (Control ctl in panel2.Controls)
   {
                if (ctl is PictureBox)
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }

SHOULD read:

foreach (Control ctl in panel2.Controls)
   {
                if (ctl is TransparentPictureBox) // <-------- this little bugger is the source of pain
                {
                    ctl.MouseDown += new MouseEventHandler(ctl_MouseDown);
                    ctl.MouseMove += new MouseEventHandler(ctl_MouseMove);
                    ctl.MouseUp += new MouseEventHandler(ctl_MouseUp);
                }
            }

Hope this helps, and we can call this one solved lol
That fixed, cheers!

I'm going to do some playing around with it though, as it flickers a lot, so I think I may add the transparency on the dropped image, but when the image is moving, keep the transparency off.


Anyway, sorry to have kept this one open so long, thanks again!
No problem, the flickering is just because of the delay, and the refresh rate, not much I can image you could do about that, other than do what you suggest.