I'm trying to first draw a shape (which i've done already) and then have it transformed as selected by a user for example, rotated to a certain angle, or scaled, showing this original shape and the newly transformed shape.
I've tried the following on trying to rotate:
Private Sub paint_box_Paint(sender As Object, e As PaintEventArgs) Handles paint_box.Paint
Dim x As Integer = paint_box.Size.Width / 2
Dim y As Integer = paint_box.Size.Height / 2
Dim rect As New Rectangle(x, y, 80, 80)
' Create pen.
Dim blackPen As New Pen(Color.Black, 3)
' Create pen.
Dim redPen As New Pen(Color.Red, 3)
e.Graphics.DrawRectangle(blackPen, rect)
End Sub
I was expecting to have that shape printed on Form.Load
to rotate by the specified angle 30.0F
When we want to paint on a Control's surface, we need subscribe to the Paint event of a Control (not all controls provide this event: TextBox controls don't, for example. We could derive a Custom Control class from TextBox and override the OnPaint
method. It may be disappointing, though).
To paint and rotate a shape, we need some Fields or Properties to store the references of the objects/values we use for painting. Here, just the Rectangle
object that provides the measure of the shape and a single
Field to store the rotation angle.
Private drawingRect As Rectangle = New Rectangle(50, 50, 100, 100)
Private rotationAngle As Single = 0.0F
These references allow to change the shape of the object and the rotation angle when needed. When these values change, we just need to call the Invalidate() method of a Control to raise its Paint
event.
In Form.Load()
(or in the Form's constructor - Public Sub New()
) we can define the initial position and size of the shape, if required:
Public Sub New()
InitializeComponent()
drawingRect = New Rectangle(50, 50, 100, 100)
End Sub
When we change the measures of a shape, to update the drawing, we call the Control's Invalidate()
method. Here, the drawing surface is provided by a GroupBox control.
On a Button.Click()
, we update the shape with the new values calling GroupBox.Invalidate()
. The drawing will be updated immediately:
Private Sub btnRotate_Click(sender As Object, e As EventArgs) Handles btnRotate.Click
' Rotate the shape 45 degrees
rotationAngle = 45
GroupBox1.Invalidate()
End Sub
To rotate a shape, we can use two simple methods: the Graphics.RotateTransform method, or the Matrix.RotateAt() method.
I'm using the latter: it's very simple to use, it accepts an angle expressed in degrees and the we just need to provide the coordinates of the rotation.
Here, the shape is rotated using the coordinates of its center point:
Using mx As Matrix = New Matrix
mx.RotateAt(rotationAngle, New PointF(drawingRect.X + (drawingRect.Width / 2.0F),
drawingRect.Y + (drawingRect.Height / 2.0F)))
e.Graphics.Transform = mx
e.Graphics.DrawRectangle(pen, drawingRect)
End Using
Sample of the results:
See also:
Drawing and scaling rectangle using a ratio
How to use the Paint event to draw shapes at mouse coordinates
All the code used to draw and rotate the shape:
Public Class Form1
Private drawingRect As Rectangle = Rectangle.Empty
Private rotationAngle As Single = 0.0F
Public Sub New()
InitializeComponent()
drawingRect = New Rectangle(50, 50, 100, 100)
End Sub
Private Sub GroupBox1_Paint(sender As Object, e As PaintEventArgs) Handles GroupBox1.Paint
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
Using pen As Pen = New Pen(Color.LightGreen, 4),
mx As Matrix = New Matrix()
mx.RotateAt(rotationAngle, New PointF(drawingRect.X + (drawingRect.Width / 2.0F),
drawingRect.Y + (drawingRect.Height / 2.0F)))
e.Graphics.Transform = mx
e.Graphics.DrawRectangle(pen, drawingRect)
End Using
End Sub
Private Sub btnPaint_Click(sender As Object, e As EventArgs) Handles btnPaint.Click
' Redefine the shape and redraw it
drawingRect.Location = New Point(100, 100)
drawingRect.Size = New Size(200, 300)
GroupBox1.Invalidate()
End Sub
Private Sub btnRotate_Click(sender As Object, e As EventArgs) Handles btnRotate.Click
' Rotate the shape 45 degrees
rotationAngle = 45
GroupBox1.Invalidate()
End Sub
End Class