ForgeMonkey ForgeMonkey - 2 months ago 21
Vb.net Question

VB.NET Rotate graphics object around center

Apologies in advance if this is a stupid question.

I have a graphics object manipulating an image that I'm drawing over a panel with a background. What I want to do is have the image rotate around its center.
Here's the code I have the to the moment:

Global declarations:

Dim myBitmap As New Bitmap("C:\Users\restofthefilepath")
Dim g As Graphics


Form1_Load:

g = Panel1.CreateGraphics


Timer1_tick (set to 1s intervals):

Panel1.Refresh()
g.DrawImage(myBitmap, -60, 110)
g.RenderingOrigin = New Point(160, 68)
g.RotateTransform(10)


And I get this: Left is after the first tick, Right is after the second tick.
enter image description here

(placeholder graphics)

As you can see I'm setting RenderingOrigin (as suggested in this answer): , but the rotation is still around 0,0. I've tried implementing RotateTransform(10, 160, 68) (with the centre of rotation specified) as this documentation says should be possible, but I get a build error "Overload resolution failed because no accessible 'RotateTransform' accepts this number of arguments".

Where am I going wrong, and how do I get the image to rotate around its center?

Answer

I started a new VB.NET Windows Forms project. I added a Panel of 200px x 200px and a Button to pause the animation as desired. I gave Panel1 a background image:

enter image description here

Made an image a little like yours:

enter image description here

and used the following code:

Public Class Form1

    Dim wiggle As Bitmap
    Dim tim As Timer

    Sub MoveWiggle(sender As Object, e As EventArgs)
        Static rot As Integer = 0
        Panel1.Refresh()

        Using g = Panel1.CreateGraphics()
            Using fnt As New Font("Consolas", 12), brsh As New SolidBrush(Color.Red)
                ' the text will not be rotated or translated
                g.DrawString($"{rot}°", fnt, brsh, New Point(10, 10))
            End Using
            ' the image will be rotated and translated
            g.TranslateTransform(100, 100)
            g.RotateTransform(CSng(rot))
            g.DrawImage(wiggle, -80, 0)
        End Using

        rot = (rot + 10) Mod 360

    End Sub

    Private Sub bnPause_Click(sender As Object, e As EventArgs) Handles bnPause.Click
        Static isPaused As Boolean = False
        If isPaused Then
            tim.Start()
            bnPause.Text = "Pause"
        Else
            tim.Stop()
            bnPause.Text = "Start"
        End If

        isPaused = Not isPaused

    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        wiggle = New Bitmap("C:\temp\path3494.png")
        wiggle.SetResolution(96, 96) ' my image had a strange resolution
        tim = New Timer With {.Interval = 50}
        AddHandler tim.Tick, AddressOf MoveWiggle
        tim.Start()

    End Sub

    Private Sub Form1_Closing(sender As Object, e As EventArgs) Handles MyBase.Closing
        RemoveHandler tim.Tick, AddressOf MoveWiggle
        tim.Dispose()
        wiggle.Dispose()

    End Sub

End Class

and achieved this:

enter image description here

Note 1: It is important to set the transformations in the correct order.

Note 2: I called .Dispose() on the disposable resources in the MyBase.Closing event. This makes sure that memory is left clean and nothing leaks.

There are undoubtedly better ways to create animations, but at your desired one frame per second this achieves the effect you're after.

Comments