[Last Call] Learn about multicloud storage options and how to improve your company's cloud strategy. Register Now

x
?
Solved

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

Posted on 2007-04-06
21
Medium Priority
?
521 Views
Last Modified: 2012-06-27
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!
0
Comment
Question by:Cyber-Drugs
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 12
  • 9
21 Comments
 
LVL 5

Expert Comment

by:Yttribium
ID: 18867722
If you could show me what you've done, then I can see if I can do anything.
0
 
LVL 5

Expert Comment

by:Yttribium
ID: 18867781
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18870319
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 5

Expert Comment

by:Yttribium
ID: 18870345
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18870500
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18870507
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
 
LVL 5

Expert Comment

by:Yttribium
ID: 18870524
Can't connect unfortunately, ACCESS DENIED  =/
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18870538
Ah yeah, sorry forgot...

Can you possibly email your IP address to me so I can grant access: developer@cyber-lane.com
0
 
LVL 5

Expert Comment

by:Yttribium
ID: 18870552
done *waits* hehe
0
 
LVL 5

Expert Comment

by:Yttribium
ID: 18870633
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
 
LVL 5

Expert Comment

by:Yttribium
ID: 18870675
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18872091
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
 
LVL 5

Accepted Solution

by:
Yttribium earned 2000 total points
ID: 18872110
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
 
LVL 5

Expert Comment

by:Yttribium
ID: 18872113
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18872967
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18872980
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
 
LVL 5

Expert Comment

by:Yttribium
ID: 18872989
What happened?  Drag and drop still works for me I think... what do you mean - it doesn't work? :s
0
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18873001
Maybe I've done something wrong?


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


http://www.cyber-lane.com/CartoLogix.zip
0
 
LVL 5

Expert Comment

by:Yttribium
ID: 18873080
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
 
LVL 4

Author Comment

by:Cyber-Drugs
ID: 18873139
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
 
LVL 5

Expert Comment

by:Yttribium
ID: 18873196
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

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
This article is for Object-Oriented Programming (OOP) beginners. An Interface contains declarations of events, indexers, methods and/or properties. Any class which implements the Interface should provide the concrete implementation for each Inter…
We’ve all felt that sense of false security before—locking down external access to a database or component and feeling like we’ve done all we need to do to secure company data. But that feeling is fleeting. Attacks these days can happen in many w…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Suggested Courses

650 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question