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!
LVL 4
Cyber-DrugsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

YttribiumCommented:
If you could show me what you've done, then I can see if I can do anything.
0
YttribiumCommented:
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.
0
Cyber-DrugsAuthor Commented:
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!
0
Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

YttribiumCommented:
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.
0
Cyber-DrugsAuthor Commented:
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!
0
Cyber-DrugsAuthor Commented:
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.
0
YttribiumCommented:
Can't connect unfortunately, ACCESS DENIED  =/
0
Cyber-DrugsAuthor Commented:
Ah yeah, sorry forgot...

Can you possibly email your IP address to me so I can grant access: developer@cyber-lane.com
0
YttribiumCommented:
done *waits* hehe
0
YttribiumCommented:
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.
0
YttribiumCommented:
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
0
Cyber-DrugsAuthor Commented:
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!!!
0
YttribiumCommented:
I've added a border now for you and a colour for the border:

      public class TransparentPictureBox : Control
      {
            private Timer refresher;
            private Image _image = null;
            private BorderStyle _borderStyle;
            private Brush _borderColor = Brushes.Black;

            /// <summary>
            /// Example Brushes.Color  (Brushes is a static class)
            /// </summary>
            public Brush BorderColor
            {
                  get { return _borderColor; }
                  set { _borderColor = value; }
            }

            public BorderStyle BorderStyle
            {
                  get { return _borderStyle; }
                  set { _borderStyle = value; }
            }      

            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));
                  }
                  
                  if (_borderStyle == BorderStyle.FixedSingle)
                  {
                        e.Graphics.DrawRectangle(new Pen(_borderColor, 1), 0, 0, _image.Width - 1, _image.Height - 1);
                  }

            }

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

Hope this helps.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
YttribiumCommented:
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.
0
Cyber-DrugsAuthor Commented:
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)
0
Cyber-DrugsAuthor Commented:
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....
0
YttribiumCommented:
What happened?  Drag and drop still works for me I think... what do you mean - it doesn't work? :s
0
Cyber-DrugsAuthor Commented:
Maybe I've done something wrong?


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


http://www.cyber-lane.com/CartoLogix.zip
0
YttribiumCommented:
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
0
Cyber-DrugsAuthor Commented:
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!
0
YttribiumCommented:
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.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C#

From novice to tech pro — start learning today.