Click here to Skip to main content
15,890,123 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi, Any help is appreciated.

I what to make an application where i can add multiple images (from a png file) in certain positions on a picturebox at runtime.

I understand how to create a graphics object and this graphic is displayed in the picturebox.

What is the best way to do this if i want to add one image then place another one of the same but rotated 45 degrees, then another rotated a bit more etc... all on the same picturebox, and in the position i click.

Do i use one 'master' graphics object which is what the picture box is showing.

Then when i add a new rotated image, i create a temp graphics object containing the image, do the rotate on that object.. and then somehow add this to the 'master' graphics object.. which is then displayed in the picture box.

At times i may want to remove one of the images added and add a different one.

Any help would be great,
Thanks, Simon.

What I have tried:

I have tried lots of different ways, but it doesn't work as i want.
Posted
Updated 11-Jun-16 8:55am

It makes no sense at all. Just don't use PictureBox control at all, that's it. It is not an image.

It's hard for me to understand why so many inquirers have been confused by this purely redundant control. Its sole purpose is to reduce amount of work needed to do simplest chores, showing a single static image. Anyone could do it directly, without this control. If you want anything a bit more complicated, the controls becomes a hassle, instead of help.

Please see my past answers:
Append a picture within picturebox,
draw a rectangle in C#,
How do I clear a panel from old drawing.

What to do? The answers reference above already explained that: you create your own custom control and override OnPaint or handle the event Paint. Alternatively, you can use a control like Panel, or even Form. In that method or a handler method, you render what you want and how you want; which includes rendering some images.

For further detail in rendering, please see my past answers:
What kind of playful method is Paint? (DataGridViewImageCell.Paint(...)),
capture the drawing on a panel,
Drawing Lines between mdi child forms.

—SA
 
Share this answer
 
v2
Comments
Member 12293916 10-Jun-16 15:46pm    
Hi, Thanks for the quick reply... I have read your posts and written the code below.

I have a list of structure which holds all the images, locations, and angles, to draw on to the panel.

This works well... but how do i do the rotate.. Each click should add another image at 10 degrees to the last one...

Thanks, Simon...

CODE:

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
MyImage = System.Drawing.Image.FromFile(Application.StartupPath & "\data\testimage.png")
End Sub

Private Sub Panel1_MouseUp(sender As Object, e As MouseEventArgs) Handles Panel1.MouseUp
Rotation_Angle = Rotation_Angle + 10

Instance_Struct_Images.TheImage = MyImage
Instance_Struct_Images.Postion = New Point(e.X, e.Y)
Instance_Struct_Images.Angle = Rotation_Angle
List_of_images.Add(Instance_Struct_Images)

Panel1.Invalidate()
End Sub

Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
'e.Graphics.RotateTransform(Rotation_Angle)
For p = 0 To List_of_images.Count - 1
Instance_Struct_Images = List_of_images(p)
e.Graphics.DrawImage(Instance_Struct_Images.TheImage, Instance_Struct_Images.Postion)
Next
End Sub
Sergey Alexandrovich Kryukov 10-Jun-16 16:05pm    
To rotate, use Graphics.Transform. Make transform conditional, depending on some data model of your control. Change data, call Invalidate, and it will send WM_PAIN and re-draw the image with changed data (angle of rotation, or no rotation at all).

To avoid flicker, set optimized double buffering for your control.

Now, I answered your original question. Will you accept the answer formally?

Rotation wasn't the part of this original question. If you need more explanation of rotation, it would be another answer...

—SA
Sergey Alexandrovich Kryukov 10-Jun-16 16:06pm    
...Ah, I can see: you already used e.Graphics.Rotate transform. Any problems?
Anyway, even if there are some, you are pretty close to the solution...
—SA
Member 12293916 11-Jun-16 10:57am    
Hi, i've accepted your answer and rated it. Thanks for the help. I have got the code to rotate the image on each click now and place it on the panel where i click... to do this i have declared a tmp image, tmp bitmap and tmp graphics object. I don't know if there is a better way to do this but this seems to work.

In my code you will see i made the bitmap twice the size on the original image, this is because a rotated image width and height is larger than a non rotated image.

CODE:
tmp_modifying_image = Instance_Struct_Images.TheImage.Clone()
tmp_modifying_bitmap = New Bitmap(ImageSizeXY * 2, ImageSizeXY * 2)
tmp_modifying_graphics = Graphics.FromImage(tmp_modifying_bitmap)
tmp_modifying_graphics.TranslateTransform(ImageSizeXY / 2, ImageSizeXY / 2)
tmp_modifying_graphics.RotateTransform(Instance_Struct_Images.Angle)
tmp_modifying_graphics.TranslateTransform(-ImageSizeXY / 2, -ImageSizeXY / 2)
tmp_modifying_graphics.DrawImage(tmp_modifying_image, draw_posxy, draw_posxy) ', ImageBounds.Width, ImageBounds.Height)
Instance_Struct_Images.TheImage = tmp_modifying_bitmap.Clone()

tmp_modifying_bitmap.Dispose()
tmp_modifying_image.Dispose()
tmp_modifying_graphics.Dispose()

List_of_images.Add(Instance_Struct_Images)

---

If you have any better suggestions that would be great. At the min i make the bitmap x2 bigger so the rotated image will fit in it... Is there a way after rotating, to resize the bitmap back to the size of the rotate image in it?? I guess cropping to the bounds of the image would be the way??

Many thanks,
Simon
Sergey Alexandrovich Kryukov 11-Jun-16 12:30pm    
No, this is not a good way at all. I already explained the better way above. If you did not get it: the angle in translate should be the instance property of your control, so it will be accessible from your handler, as well as from the handler of the events (such as mouse events), where you can modify it and call Invalidate.
—SA
Simon asked:
Hi, Sorry... this is a bit above me… Are you able to do a quick example? It would be really appreciated. Best regards,
Simon
This is a separate question related to the interactive behavior of graphics, in response to some input event. I already described the principle in my past answers referenced in Solution 1.

The schema of the solution may look something like
C#
using System.Windows.Forms;
using System.Drawing;

//...

class MyControl : Control {

   static readonly double Increment = System.Math.PI * 5;
   
   double RotationAngle;

   protected override void OnMouseDown(MouseEventArgs e) {
       RotationAngle += Increment;
       Invalidate();
   }

   protected override void OnPaint(PaintEventArgs e) {
       // draw something with e.Graphics;
       var matrix = new System.Drawing.Drawing2D.Matrix();
       // decide around what point to rotate the way you want:
       PointF centerOfRotation = new System.Drawing.PointF(/* calculate it... */);
       matrix.Rotate(RotationAngle, centerOfRotation);
       e.Graphics.Transform = matrix;
       // draw something else...
       // optionally:
       e.Graphics.ResetTransform();
       // draw something else...
   }

}

Sorry for showing C# code, not VB.NET; I just don't want to waste time for it. You can easily translated it to VB.NET by yourself, manually or using many of the available tools. You only need to understand the principles.

You can add a lot of detail: limit the area where you respond to mouse click, make the increment value depending on some factors, invalidate only certain region or rectangle inside the client area of the control, and so on.

—SA
 
Share this answer
 
v2
Comments
Member 12293916 11-Jun-16 16:55pm    
Hi, thanks again. Sorry i don't quite understand and don't mean to keep on! If the images are drawn on a panel, will this not rotate the entire 'canvas' so all the images i have placed will rotate by the set angle? I want to be able to place one image at 10deg then place another at 20 deg etc etc..

Also vb.net does not like the protected override void text, and also doesn't like the matrix.rotate line.

Thanks, Simon
Sergey Alexandrovich Kryukov 11-Jun-16 17:04pm    
There is no essential differences with VB.NET. Do automatic translation, after all. I did not suggest panel, the example is the class derived from Control.

Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
   RotationAngle += Increment
   Invalidate()
End Sub

—SA

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