[2005] Moving a GDI+ Rectangle
After I create a Rectangle in GDI+ and specify the position and start drawing the rectangle onto the form, how can I update it's position?
It seems if I update the position and even see that the position is changed, it is still drawing in the same place as if the location for it to be drawn at is static upon specifying it
Re: [2005] Moving a GDI+ Rectangle
Without seeing the code you're using it's hard to know exactly what you're doing wrong but you don't actually "move" anything that's drawn with GDI+. The proper way to do GDI+ drawing is on the Paint event of the form or control you want to draw on. That way every time the control gets repainted your drawing gets done as well. You store the data that describes what and where will drawn in member variables and then retrieve that data in the Paint event handler and do the drawing. If you want to "move" the drawing then you simply change the data stored in those member variables and force a repaint. Your old drawing disappears and the new drawing gets performed. Nothing actually moves.
Think of it like this. Let's say that you have a wall. Someone repaints that wall every week. You leave instructions on where on that wall to paint a rectangle. Each week the painter comes and paints over the old rectangle with white paint, so it disappears. They then read your instructions and paint a black rectangle. This happens over and over every week, so each time you look at the wall it looks the same. Now one day you write out new instructions. The next time the painter comes along they paint the wall white and your old rectangle disappears. They then read the current instructions and paint a rectangle accordingly. It's in a different place to the old one, but did anything actually move?
Try this:
1. Create a new project and add a Button.
2. Add this code:
Code:
Private paintCount As Integer = 0
Private rect As New Rectangle(50, 75, 100, 150)
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.DrawRectangle(Pens.Black, Me.rect)
Me.paintCount += 1
Console.WriteLine("Rectangle drawn {0} times", Me.paintCount)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim rect As Rectangle = Me.rect
rect.Inflate(1, 1)
'Flag the area occupied by the old rectangle as needing repainting.
Me.Invalidate(rect)
Me.rect = New Rectangle(75, 50, 150, 100)
rect = Me.rect
rect.Inflate(1, 1)
'Flag the area occupied by the new rectangle as needing repainting.
Me.Invalidate(rect)
'Tell the form to repaint the invalidated areas.
Me.Update()
End Sub
Now run the project and see the initial rectangle drawn on the form. Move the form around, drag other forms over it, minimise and restore it, resize it and see that the initial rectangle remains. Now look at the Output window in the IDE and see how many times your rectangle has been drawn. You will probably be surprised. Now press the Button and see your rectangle "move". What actually happened was that the form was repainted and the current data used to draw a new rectangle.
Re: [2005] Moving a GDI+ Rectangle
That is quite a bit just for getting the image to repaint.. wow. anyways, it seems to work. i'll look it over and convert to c#
thanks
Re: [2005] Moving a GDI+ Rectangle
Just keep in mind that I've stretched that code out for illustrative purposes. You could just do this:
Code:
Private rect As New Rectangle(50, 75, 100, 150)
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
e.Graphics.DrawRectangle(Pens.Black, Me.rect)
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Me.rect = New Rectangle(75, 50, 150, 100)
Me.Refresh()
End Sub
and get the same result. That said, it's generally preferable to use the Invalidate and Update methods rather than the Refresh method so that you can repaint as little of the control as possible. In many cases it will make no significant difference but in some cases repainting the entire control when only one small part has changed will noticeably affect performance.
Re: [2005] Moving a GDI+ Rectangle
Thanks for the additional help. Really, you're the only person that ever responds to my topics and I repped you last time so I can't really rep you again, sorry. I suppose I could just go rep some random person so I can rep you again but whatever..
Point is I appreciate your help and you don't need green blocks under your name to prove it I guess.
Thanks. Resolved.
Re: [2005] Moving a GDI+ Rectangle
hey, im very noob at vb, but the way i made it move was by creating a picturebox and making the visible = false, and set the x, and y coordinates as picturebox.left and picturebox.top :D and then i moved the picturebox.....
its allot easier :)
Re: [RESOLVED] [2005] Moving a GDI+ Rectangle
Hey John. I know this is resolved but I have another question pertaining to this topic.
I have a rectangle.
I have to invalidate the rectangle before AND after i change the position of it.
So then i need to pass the Form to the class method.
Now I have gotten less OOP just by doing that. And eventually I need to do this for 4 rectangles.
Eventually, it gets a bit out of hand.
Is there not a better solution where when you update a rectangle's position it automatically redraws the rectangle?
Thanks a lot
Re: [2005] Moving a GDI+ Rectangle
Uhm..
For example, could I override the Location property of the Rectangle class so that the instance of the rectangle accessing the Position property would then be Invalidated after the Position is changed inside of the property.
How would I do something like this? Thanks
Re: [2005] Moving a GDI+ Rectangle
Rectangle is a structure, not a class, although there is a Rectangle class too. The one used in relation to drawing is a structure though, so there's no inheriting it.
The reason you invalidate the rectangle before and after the change is that the form needs to redraw the area where the old rectangle was to remove it, then redraw the area where the new rectangle is. By invalidating twice you ensure that the smallest area possible gets redrawn and thus the operation is as fast as possible.
What you could do is create class that contains a Rectangle and a Form reference. You can then access members of an instance of that class and it will handle invalidating the form and updating the Rectangle. Lo and behold, the Microsoft VB Power Packs download contains classes that will basically do that for lines, rectangles and ellipses.