0

I'm trying to rotate a picture box called player1 with the following command

  e.Graphics.RotateTransform(angle)

e.Graphics.DrawImage(BMP, New Point(-player1.Width \ 2, -player1.Height \ 2))

player1.Refresh()

However it seems to place the picture that i have drawn outside the picture box near the top left of the picturebox, i believe that is the current origin. Also, it only rotates about the origin located at the top left. I would like to set the rotation point / origin of the picture box to the centre. Thanks!

fboi1
  • 3
  • 3
  • 2
    You're not rotating a PictureBox, you're trying to rotate the Image drawn in its graphics context. As mentioned before, use [Matrix.RotateAt()](https://learn.microsoft.com/en-us/dotnet/api/system.drawing.drawing2d.matrix.rotateat), it's simpler to handle. Remove that `player1.Refresh()` from there: you need to `Invalidate()` your PictureBox when the Mouse moves. You should mention the SizeMode of your PictureBox (in case it's `StretchImage` or `Zoom`). – Jimi Jun 30 '20 at 21:48
  • See, for example. here: [Zoom and translate an Image from the mouse location](https://stackoverflow.com/a/61964222/7444103). The TrackBar defines the rotation angle. See how much it takes to rotate that Bitmap, scaled and translated, using `Matrix.RotateAt()` (how many lines of code are needed in `canvas_Paint()` to generate all those *effects* -> `canvas` is a PictureBox). – Jimi Jun 30 '20 at 21:55
  • Thank you for informing me about the Matrix.RotateAt() command. If i remove player1.Refresh() everything stops moving. Also, what do you mean by Invalidate() ? Thanks – fboi1 Jun 30 '20 at 22:11
  • Write `player1.Invalidate()`, put the caret inside the `Invalidate()` part and press `F1`. I also linked code that does just that in more than one place. – Jimi Jun 30 '20 at 22:14
  • You really ought to have done a bit more reading on how GDI+ works. The `Invalidate` method is what tells the system what area of the control gets repainted on the next `Paint` event. The idea is that, when you want to change the drawing, you change the data that represents the drawing and then call `Invalidate`. A `Paint` event is then queued and you do the drawing in the event handler. If you want the `Paint` event raised immediately, you can call `Update`. The `Refresh` method simply calls `Invalidate` and `Update`. Why force a `Paint` event inside the `Paint` event handler? – jmcilhinney Jul 01 '20 at 00:33
  • Also, if you call `Invalidate` with no argument, you are going to repaint the entire control, which is inefficient. You should specify a `Region` or `Rectangle` that defines the smallest area that might have changed. That way, the minimum possible number of pixels gets repainted and that is more efficient. You can even call `Invalidate` multiple times with multiple different areas to keep the overall area as small as possible. You still draw everything in the `Paint` event handler but not all pixels will be repainted. – jmcilhinney Jul 01 '20 at 00:36

1 Answers1

0

I would like to set the rotation point / origin of the picture box to the centre.

Just use TranslateTransform before you rotate:

e.Graphics.TranslateTransform(player1.Width / 2, player1.Height / 2)
e.Graphics.RotateTransform(angle)
e.Graphics.DrawImage(BMP, New Point(-player1.Width \ 2, -player1.Height \ 2))

Depending on what operations you had done previously with e.Graphics, sometimes you have to ResetTransform() to put things back to the way they were at the beginning of the Paint() event before you Translate/Rotate/Draw.

Idle_Mind
  • 38,363
  • 3
  • 29
  • 40