Click here to Skip to main content
15,798,592 members
Please Sign up or sign in to vote.
4.83/5 (3 votes)
See more:
Hi there,

I want to build a form where the user is able to add simple overlays (circle, arrow) to a photo. I'd really love to be able to drag and transform (like squeeze the circle to an ellipse) the overlay images. My idea was to use transparent png's (like red arrow on transparent background). I'm not quite sure if I can use a PictureBox to achieve the above.

Yes, I used the search but didn't quite find what I was looking for.

Thanks in advance for any help.
Updated 17-May-11 12:21pm
Sergey Alexandrovich Kryukov 17-May-11 16:56pm    
Tag it! Forms.
DaveyM69 17-May-11 17:22pm    
If you 'Improve Question' you can retag. I've done this one :-)
Sergey Alexandrovich Kryukov 17-May-11 19:28pm    
I know. I just wanted to bring OP's attention to tags. OP is the most interested party, the one who need to attract right experts to a question.
Sergey Alexandrovich Kryukov 17-May-11 17:20pm    
This is good that you're not sure! Many others are sure and make a fatal mistake which destroyed many projects. I'm helping you to do it right, which is quite feasible, was successfully done in many variants. My 5 for the question.

Don't do a big common mistake: don't do your on screen rendering using PictureBox!
As much of your work is dynamic rendering of the images on screen, I would avoid using PictureBox at all. (You could use it, but I cannot see where it helps in your case except in eating up extra resources and performance.)

So, use some Control as a container for graphics. It can be some Panel, but it can be more convenient to create your custom control class derived from <code>System.Windows.Forms.Control. Do all rendering in overridden OnPaint method of control. If you don't want to create a custom control, use Panel.Paint event handler. In both cases, use the instance of System.Drawing.Graphics you get from event arguments parameter (never create Graphics instance using its constructor).

You should do all changes of graphic using some data model. The rendering event only translates the data model by rendering it on the Windows message WM_PAINT. For example, your data includes an instance of Bitmap (your photo), its position, positions and parameters of some graphics primitives you put on top — texts, rectangles, etc.: colors (with alpha channel showing opacity), sizes, orientation. Draw your photo at the very background using Graphics.DrawImage. (You see, you don't need PictureBox.) You can support some container of graphical elements.

Now, when you drag an element or change some parameters, you need to refresh the image. The only valid way to do it is calling Control.Invalidate. Use Invalidate with parameters (Rectangle or Region) to improve performance: these method will invalidate only a part of the scene.

In your control, don't forget to use Control.SetStyle to add the style System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer | System.Windows.Forms.ControlStyles.OptimizedDoubleBuffer.AllPaintingInWmPaint. It will help to avoid flicker. By the way, this is a protected method, so this is another reason to use derived custom control.

You need to write you rendering method as a separate method, not inside of the handler (which will call your method). Why? Because you also need to do all the rendering on the image itself!

When you need to safe you image with overlays, you will create in instance of the Graphics using Graphics.FromImage and draw on your image using this instance and your rendering method. That's why I recommended to abstract it out — to draw on different object: the screen during editing and on the photo before you save it.

Share this answer
I'd recommend you do not to use any controls for these overlays. That's because Windows Forms do not support real transparency. When you add a control with background transparency over another one, what actually happens is that the background of the control under it gets copied to the background of the control overlaying it.

This can lead to two problems:

1 - Sometimes the copying process does not work very well. Specially if there are several layers, some glitched are likely to happen and the simulated transparency might not look correctly.

2 - Since this is not real transparency, the performance might not be so good if you actually just drew over the original image.

So my suggestion is, that you draw this images over it only and create your own mechanisms to draw each object you have over the original image. You can create your own way of dragging and moving the image and only really draw what needs to be drawn, so you don't use any control and don't paint any background.

I hope you find this useful.

Share this answer
Sergey Alexandrovich Kryukov 17-May-11 19:26pm    
This is correct, but I already offered the complete skeleton of the right design.
Transparency in this case is just using alpha channel in colors. GDI+ perfectly supports transparency in this way.
Fabio Franco 17-May-11 23:50pm    
You're right, I mistakenly read your solution suggested to use controls to draw over the original image. In any case, I completly agree with your solution and I think I put in some more information that will add to yours.

Anyways, I guess I've put the info in the wrong place, I should've added as a comment.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900