Results 1 to 7 of 7

Thread: [RESOLVED] Drawing gdi+ flickering??? Heeeelp!

  1. #1

    Thread Starter
    New Member
    Join Date
    Sep 2012
    Posts
    15

    Resolved [RESOLVED] Drawing gdi+ flickering??? Heeeelp!

    I have a Class which inherits a UserControl. The aim is to graphically display the sound input/output. The Property "Value" of Animation Class, receives the current value of the sound in realtime between 0 and 100, which i update from an outside Class via a Timer(50MSec.)

    I managed it all to work but i am facing an annoying problem, the animation flickers. I raised the Thread.Priority into Highest, no effect, so i dont believe a separate Thread would do better. I researched and know now basically where the problem lies, but still cant figure out how to handle it. I have tried as in the beginning the ME.CreateGraphics Method, it flickered, then overrided OnPaint Method and painted with e.Graphics. The result was a blank control! Thanks for any help!

    Here is a small demo of the code, an example



    Code:
    Public Class Form1
        Private [DISPLAY] As Form 'A SEPARATE FORM THAT CONTAINS THE USERCONTROL "ANIMATION" & DISPLAYS IT
        Private _Animation As Animation
        Private Shadows Sub [load]() Handles MyBase.Load
            DISPLAY = New Form
            _Animation = New Animation
            DISPLAY.Controls.Add(_Animation)
            _Animation.Dock = DockStyle.Fill
            DISPLAY.Show()
            Dim tmr As New Timer(New System.ComponentModel.Container)
            tmr.Interval = 50
            AddHandler tmr.Tick, AddressOf Looper
            tmr.Start()
        End Sub
        Private Sub Looper()
            _Animation.Value = Now.Second 'AN EXAMPLE
        End Sub
    End Class
    
    Public Class Animation
        Inherits UserControl
        Private _Value As UInt32
        'EVERYTIME VALUE IS CHANGED IT WILL REPAINT THE CONTROL
        Public Property Value As UInt32
            Get
                Return _Value
            End Get
            Set(ByVal value As UInt32)
                _Value = value
                [Refresh]()
            End Set
        End Property
        Sub New()
            ' InitilizeComponent()
            Countleds()
        End Sub
        Private LEDs As Integer
        'COUNT THE AMOUNT OF LEDS POSSIBLE TO FIT IN CONTROL
        Private Sub Countleds() Handles Me.SizeChanged
    
            dictOfLeds.Clear()
    
            LEDs = 0
            If Me.Width < SizeCurrent Then
                LEDs = 1
            Else
                Dim _MeWidth As Integer = Me.Width - SizeCurrent
                LEDs = (_MeWidth \ (SizeOld + Space)) + 1
            End If
    
            For i As UInteger = 1 To LEDs Step +1
                dictOfLeds.Add(i, 0)
            Next
            'MsgBox(LEDs)
        End Sub
        Private dictOfLeds As New Dictionary(Of UInt32, UInt16)
        Private Space As Integer = 2
        Private SizeCurrent = 7
        Private SizeOld As Integer = 3
        Private ColorOld As Brush = New SolidBrush(Color.Aqua)
        Private ColorCurrent As Brush = New SolidBrush(Color.Blue)
        Private _Pen As New Pen(Brushes.AliceBlue, 5.0F)
        Private _StartPoint As New Point(0, 0)
        Private _EndPoint As New Point(0, 0)
        'THIS SUB WILL BE CALLED WHENEVER THE "[Value]" Property is changed
        Private Shadows Sub [Refresh]()
            For i = LEDs To 2 Step -1
                If i = 2 Then dictOfLeds(1) = Value
                dictOfLeds(i) = dictOfLeds(i - 1)
            Next
            Me.CreateGraphics.Clear(Color.Green)
            Dim int As Integer
            For i As Integer = 1 To LEDs Step +1
                If i = 1 Then
                    int = (SizeCurrent \ 2) + Space
                    _Pen.Width = SizeCurrent
                    _Pen.Brush = ColorCurrent
                ElseIf i = 2 Then
                    int = (SizeCurrent + Space) + ((SizeOld \ 2) + Space)
                    _Pen.Width = SizeOld
                    _Pen.Brush = ColorOld
                ElseIf i > 2 Then
                    int += SizeOld + Space
                    _Pen.Width = SizeOld
                    _Pen.Brush = ColorOld
                End If
                Dim _location As New Point(0, CInt(Me.Height \ 2))
                _StartPoint.X = (Me.Width) - int
                _StartPoint.Y = (_location.Y - (Me.Height / 2) + dictOfLeds.Item(i))
                _EndPoint.X = (Me.Width) - int
                _EndPoint.Y = (_location.Y + (Me.Height \ 2) + (Me.Height / 2) + dictOfLeds.Item(i))
                'Me.Invalidate() to raise Onpaint when painting via Onpaint
               
     Me.CreateGraphics.DrawLine(_Pen, _StartPoint, _EndPoint)
            Next
    
        End Sub
    Protected Overrides Sub Onpaint(Byval sender as Object, Byval e as painteventargs)
    'WHEN PASSED THE e.graphics.drawline(_pen,_startpoint, _endpoint) result was nothing
    End Sub
    End Class
    The result looks like this in my project (not the above code). the capture looks good but in reality it flickers while refreshing!

    Name:  OriginalProjectsResult.png
Views: 789
Size:  54.4 KB
    Last edited by Begi; Feb 9th, 2014 at 01:55 PM.

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Drawing gdi+ flickering??? Heeeelp!

    How to: Reduce Graphics Flicker with Double Buffering for Forms and Controls:

    http://msdn.microsoft.com/en-us/libr...v=vs.110).aspx

  3. #3

    Thread Starter
    New Member
    Join Date
    Sep 2012
    Posts
    15

    Re: Drawing gdi+ flickering??? Heeeelp!

    Thanks for the reply, i have tried it out before but i coulnt see any difference, maybe because i was using Me.CreateGraphics.

    Do you have any clue why when i pass the e.Graphics.Drawline(_pen, _StartPoint, _EndPoint) to OnPaint it doesnt refresh anything? I used to call it via Me.Invalidate, Me.Refresh, Me.Update but the OnPaint doesnt reflect the code given?

    Anyone help!

  4. #4
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Drawing gdi+ flickering??? Heeeelp!

    CreateGraphics causes all kinds of trouble when used for drawing. Your OnPaint sub won't have any effect if you have left out MyBase.OnPaint. I suggest you transfer all the code except Invalidate from [Refresh] to OnPaint, replacing Me.CreateGraphics by e.Graphics. Unless you need it for some other reason, you could then get rid of the shadowed Refresh sub altogether and put Me.Invalidate in the property Set clause.

    To prevent flickering, put Me.DoubleBuffered = True in the UserControl's New sub.

    BB

  5. #5

    Thread Starter
    New Member
    Join Date
    Sep 2012
    Posts
    15

    Re: Control flickers when Drawing multiple elements in short times!

    Thanks boops boops, that helped. Also there was an error in my code which i realised later. Putting MyBase.OnPaint(e) at the end of OnPaint() clause was not necessary.


    Here is the solution for other people having flickering Controls, i also have found a manual way to buffer the drawings on Web, but setting Me.DoubleBuffered = True would be less code;


    Code:
    Class TEST
     Inherits Form       ' or Inherits UserControl whatever!
    
        Private _doBuffer As Boolean = False ' We will use the automated solution Me.DoubleBuffered = True, otherwise Me.DoubleBuffered = False if using "_doBuffer"
        Private _backBuffer As Bitmap
    
    
    Sub New
     Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer, True)
    End Sub
    
    'CALL THIS SUB WHENEVER YOU WANT TO PAINT THE STUFF ON "OnPaint()"
      PUBLIC SUB Paint_MyStuff
        Invalidate 
      End Sub
    
     Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
            If _backBuffer Is Nothing Then
                _backBuffer = New Bitmap(Me.ClientSize.Width, Me.ClientSize.Height)
            End If
            Dim g As Graphics = Nothing
    
            If _doBuffer Then
                g = Graphics.FromImage(_backBuffer)
            Else
                g = e.Graphics
            End If
            g.Clear(Me.BackColor)
    
    
    '''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
    'STUFF TO DRAW ON CONTROL;
            For i As Integer = 0 To Me.Height Step +1
                g.DrawLine(New Pen(Brushes.Blue, 1.0F), New Point(0,0), New Point(Me.Width, i))
            Next
    ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
           
            If _doBuffer Then
                g.Dispose()
                'Copy the back buffer to the screen
                e.Graphics.DrawImageUnscaled(_backBuffer, 0, 0)
            End If
            MyBase.OnPaint(e) '//optional but not recommended
        End Sub 'OnPaint
      
    
        Protected Overrides Sub OnPaintBackground(ByVal pevent As PaintEventArgs)
        'Do stuff (OPTIONAL)
        End Sub 'OnPaintBackground
    
    
        'Don't allow the background to paint
        Protected Overrides Sub OnSizeChanged(ByVal e As EventArgs)
            Me.CreateGraphics.Clear(Me.BackColor)
            
            If Not (_backBuffer Is Nothing) Then
                _backBuffer.Dispose()
                _backBuffer = Nothing
            End If
            MyBase.OnSizeChanged(e)
        End Sub 'OnSizeChanged
    
    End Class
    Last edited by Begi; Feb 10th, 2014 at 03:05 PM.

  6. #6
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,102

    Re: Drawing gdi+ flickering??? Heeeelp!

    By the way, you shouldn't be messing with thread prioritization unless you have a REALLY good reason. Increasing the priority of a thread doesn't mean that it gets more time, it means that it gets ALL the time. Lower priority threads only get to use the CPU if there are no higher priority threads pending. In theory, boosting your app to the highest thread priority would mean that it would be at the same level as the OS noticing keypresses, and so on. That can ruin system performance and behavior because your app is dependent on getting keyboard events from the OS, but it might block the OS from even noticing keys being pressed. In practice, the impact will not be THAT bad, but it could still be pretty horrible.
    My usual boring signature: Nothing

  7. #7

    Thread Starter
    New Member
    Join Date
    Sep 2012
    Posts
    15

    Re: Drawing gdi+ flickering??? Heeeelp!

    Sounds very logically!

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width