Flicker, flicker, flicker

TBryce311

Active member
Joined
Mar 20, 2007
Messages
25
Location
New York
Programming Experience
1-3
Pretext: I know GDI is not the best for completing the task at hand. This is more of a knowledge thing and annoiance item more than anything. The form is an inherited form template which has the doublebuffer property set to true. I have the following code:

VB.NET:
Public Class Animation
    Inherits BYTemplate2.BYTemplate

#Region "Define Brushes/Pen"
    Dim green150 As New SolidBrush(Color.FromArgb(150, 0, 255, 0))
    Dim blue75 As New SolidBrush(Color.FromArgb(75, 0, 0, 255))
    Dim red50 As New SolidBrush(Color.FromArgb(50, 255, 0, 0))
    Dim jpen As New Pen(Color.Black, 3)
#End Region

    Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
        Try
            Me.SuspendLayout()

            Dim myGraphic As Graphics = e.Graphics
            myGraphic.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias

            ' static bools for movement
            Static moveRight As Boolean = True
            Static moveDown As Boolean = True

            ' x-axis for manipulation
            Static _14 As Single = 75.0F
            Static _23 As Single = 300.0F
            Static _58 As Single = 200.0F
            Static _67 As Single = 400.0F

            'y-axis for manipulation
            Static _12 As Single = 125.0F
            Static _34 As Single = 325.0F
            Static _56 As Single = 50.0F
            Static _78 As Single = 250.0F

            ' Create points that define polygon.
            Dim point1 As New PointF(_14, _12)
            Dim point2 As New PointF(_23, _12)
            Dim point3 As New PointF(_23, _34)
            Dim point4 As New PointF(_14, _34)
            Dim point5 As New PointF(_58, _56)
            Dim point6 As New PointF(_67, _56)
            Dim point7 As New PointF(_67, _78)
            Dim point8 As New PointF(_58, _78)

            ' create the plain(s) for each side of the cube/polygon
            Dim pln1 As PointF() = {point5, point6, point7, point8}
            Dim pln2 As PointF() = {point1, point5, point8, point4}
            Dim pln3 As PointF() = {point1, point2, point3, point4}
            Dim pln4 As PointF() = {point2, point6, point7, point3}
            Dim pln5 As PointF() = {point5, point6, point2, point1}
            Dim pln6 As PointF() = {point8, point7, point3, point4}


            ' Fill polygon to screen.
            e.Graphics.FillPolygon(green150, pln1)
            e.Graphics.FillPolygon(green150, pln2)
            e.Graphics.FillPolygon(blue75, pln3)
            e.Graphics.FillPolygon(blue75, pln4)
            e.Graphics.FillPolygon(red50, pln5)
            e.Graphics.FillPolygon(red50, pln6)

            ' Draw the exterior lines
            e.Graphics.DrawPolygon(jpen, pln1)
            e.Graphics.DrawPolygon(jpen, pln2)
            e.Graphics.DrawPolygon(jpen, pln3)
            e.Graphics.DrawPolygon(jpen, pln4)

            e.Graphics.Dispose()

            If moveRight Then  ' going right
                If _67 < 889 Then  ' not all the way right yet
                    _14 += 5.0F
                    _23 += 5.0F
                    _58 += 5.0F
                    _67 += 5.0F
                Else  'ALL the way right
                    moveRight = False  'head left now
                End If
            Else
                If _14 > 15 Then  ' not all the way left yet
                    _14 -= 5.0F
                    _23 -= 5.0F
                    _58 -= 5.0F
                    _67 -= 5.0F
                Else  ' ALL the way left
                    moveRight = True 'head back to the right
                End If
            End If

            If moveDown Then    'going down
                If _34 < 500 Then     'not to bottom yet
                    _12 += 5.0F
                    _34 += 5.0F
                    _56 += 5.0F
                    _78 += 5.0F
                Else                'at the bottom
                    moveDown = False    'so start back up
                End If
            Else                    'going up
                If _56 > 25 Then     'not to top yet
                    _12 -= 5.0F
                    _34 -= 5.0F
                    _56 -= 5.0F
                    _78 -= 5.0F
                Else                'at the top
                    moveDown = True 'so start back down
                End If
            End If
            Me.ResumeLayout()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try

    End Sub

    Private Sub cmdAnimHide_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cmdAnimHide.Click
        ' hide the animation form and show the main control form (not the login page).
        Me.Hide()
        MainForm.Show()
    End Sub

    Private Sub Timer1_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles Timer1.Tick
        ' force the form to redraw
        Me.Invalidate()
    End Sub

    Private Sub Animation_Disposed(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Disposed
        LoginForm1.Close()
    End Sub

    Private Sub Animation_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        ' notify the user of how to stop the animation
        MessageBox.Show("Hold down left mouse button to stop animation.", "FYI...", MessageBoxButtons.OK, MessageBoxIcon.None)
    End Sub

    Private Sub Animation_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        ' control the animation 
        Timer1.Enabled = False
    End Sub

    Private Sub Animation_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseUp
        ' control the animation 
        Timer1.Enabled = True
    End Sub
End Class 'animation

which presents a HORRIBLE flicker. Now that is ok for my attempt and expected, but what could be done to avoid this flicker or what is a better way (other than having an image and moving the image around)?

Thank you all in advance.
 
Don't dispose the Paint events Graphics instance, it is not yours. e.Graphics.Dispose() is wrong.

You do several things here that causes the method to slow down:
- making allocation for a new variable, no variables need to be declared in your Paint method.
- SuspendLayout/ResumeLayout. Your Paint event doesn't modify any property of the control (form) and have no need to supress multiple layout event causes by such actions, so why do you turn this on/off 10 times a second? Will do nothing but slowing you down.
- You Try-Catch the full Paint code, why? Is there any call there that could cause exception? No. It will only slow down every call.
- The 5px step interval doesn't slow animation down, but make it look as it is flickering. Try 1px step and increase the speed by the timer interval.

You can also double-buffer the form painting, set these in form Load or Sub New:
VB.NET:
Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
Me.SetStyle(ControlStyles.UserPaint, True)
 
Declare the variables outside the Paint event method.
 
Back
Top