Spinning a Picture Without Flickering

Klogg

Well-known member
Joined
Oct 7, 2003
Messages
104
In my program, I rotate the image in a PictureBox 180 degrees, showing it every .05 degrees. My problem is that the image flickers because I clear it before it redraws the image at the next angle. However, when I dont clear it, it leaves a mess behind. Does anyone know how to fix this problem? Here is my code:

Code:
Dim g As Graphics = Graphics.FromHwnd(Handle)
Dim decAngle As Decimal

Me.PictureBox.Visible = False

For decAngle = 180 To 360 Step 0.05
      g.RotateTransform(decAngle)
      g.TranslateTransform(Me.PictureBox.Location.X + Me.PictureBox.Image.Width \ 2, Me.PictureBox.Location.Y + Me.PictureBox.Image.Height \ 2, Drawing2D.MatrixOrder.Append)
      g.DrawImage(Me.PictureBox.Image, Me.PictureBox.Image.Width \ 2, Me.PictureBox.Image.Height \ 2, -Me.PictureBox.Image.Width, -Me.PictureBox.Image.Height)
      g.ResetTransform()
      g.Clear(System.Drawing.SystemColors.Control)
Next decAngle

g.Dispose()

Me.PictureBox.Image.RotateFlip(RotateFlipType.Rotate180FlipNone)
Me.PictureBox.Visible = True
 
Make you own picturebox inheriting from UserControl and
call SetStyle in the contructor to set up DoubleBuffing. Look up DoubleBuffer in search and you will find many posts about this.
 
I tried doing what you suggested, but the instructions that I found arent quite specific enough for a beginner like me. In the PictureBox part of the "Windows Form Designer generated code," I put:

Code:
Me.SetStyle(ControlStyles.DoubleBuffer, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
The rest of my code now looks like this:

Code:
Private Sub PictureBox_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles PictureBox.Click
        Me.PictureBox.Visible = False

        Me.Invalidate()

        Me.PictureBox.Image.RotateFlip(RotateFlipType.Rotate180FlipNone)
        Me.PictureBox.Visible = True
    End Sub

Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        Dim g As Graphics = Graphics.FromHwnd(Handle)
        Dim decAngle As Decimal

        For decAngle = 180 To 360 Step 0.05
            g.RotateTransform(decAngle)
            g.TranslateTransform(Me.PictureBox.Location.X + Me.PictureBox.Image.Width \ 2, _
                Me.PictureBox.Location.Y + Me.PictureBox.Image.Height \ 2, Drawing2D.MatrixOrder.Append)
            g.DrawImage(Me.PictureBox.Image, Me.PictureBox.Image.Width \ 2, Me.PictureBox.Image.Height \ 2, _
                -Me.PictureBox.Image.Width, -Me.PictureBox.Image.Height)
            g.ResetTransform()
            g.Clear(System.Drawing.SystemColors.Control)
        Next decAngle

        g.Dispose()
    End Sub
The picture still flickers when its spinning, and now the Me.PictureBox.Visible = False statement appears to have no effect. Could you please tell me what I did wrong (or didnt do)?
 
try putting the
Code:
Me.SetStyle(ControlStyles.DoubleBuffer, True)
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)

in the form_load event
 
You need to paint with the Graphics from OnPaint, not FromHandle. e.Graphics.

You dont need that code in Load, just leave it in the constructor.
Also include:
Me.SetStyle(ControlStyles.UserPaint, True)
 
Also, why are you using
g.Clear(System.Drawing.SystemColors.Control)?

When you paint in OnPaint, the only thing that will remain on the control is what you paint in each OnPaint event, everything else is reset, or erased.
 
I did what you said above, but after I changed the Dim statement to Dim g As Graphics = e.Graphics, it gave me an error when I ran the program. The error was, "An unhandled exception of type System.ArgumentException occurred in system.drawing.dll."

Also, I have g.Clear in my code because when I didnt have it, it left behind the picture for every angle it painted it at. I had a square image, and by the time it was done spinning, it was a circle because none of the images were erased.
 
Ok, Ive got everything figured out except for one thing (I think). I took the For loop out of my OnPaint sub procedure, and that stopped my last problem. I added a timer to control it instead. Now, however, when I put in the Me.SetStyle stuff in, it causes a problem. Its fine until I load an image, then it comes up with the same error that I mentioned in my last post. I dont know why its doing this or how to stop it.
 
Yep, it was the g.Dispose(). It works now. Thanks for all of your help for and putting up with my ignorance of GDI+. I learned quite a bit about it from this problem.
 
I would create a bitmap in memory and do your graphics stuff to it then apply to your picture box. Nice, Fast, and No flicker at all.



Jason
 
Back
Top