How do I make this flicker-free?

The following code draws line numbers next to a RichtextBox control I have on my form. However, the code causes the LineNumbers picture box to flicker rapidly while being drawn, I was wondering if anyone could help

Private Sub DrawRichTextBoxLineNumbers(ByRef g As Graphics)

'Calculate font heigth as the difference in Y coordinate

'between line 2 and line 1

'Note that the RichTextBox text must have at least two lines.

' So the initial Text property of the RichTextBox

' should not be an empty string. It could be something

' like vbcrlf & vbcrlf & vbcrlf

With RichTextBox1

Dim font_height As Single

font_height = .GetPositionFromCharIndex(.GetFirstCharIndexFromLine(2)).Y _

- .GetPositionFromCharIndex(.GetFirstCharIndexFromLine(1)).Y

If font_height = 0 Then Exit Sub

'Get the first line index and location

Dim first_index As Integer

Dim first_line As Integer

Dim first_line_y As Integer

first_index = .GetCharIndexFromPosition(New _

Point(0, g.VisibleClipBounds.Y + font_height / 3))

first_line = .GetLineFromCharIndex(first_index)

first_line_y = .GetPositionFromCharIndex(first_index).Y

'Print on the PictureBox the visible line numbers of the RichTextBox

g.Clear(LineNumbers.BackColor)

Dim i As Integer = first_line

Dim y As Single

Do While y < g.VisibleClipBounds.Y + g.VisibleClipBounds.Height

y = first_line_y + 2 + font_height * (i - first_line - 1) - 2

If i = RichTextBox1.GetLineFromCharIndex(RichTextBox1.SelectionStart) + 1 Then

g.FillRectangle(Brushes.WhiteSmoke, 0, y, LineNumbers.Width, font_height)

g.DrawLine(Pens.SlateGray, 0, y, LineNumbers.Width, y)

g.DrawLine(Pens.SlateGray, 0, y + font_height, LineNumbers.Width, y + font_height)

End If

g.DrawString((i).ToString, .Font, Brushes.SlateGray, LineNumbers.Width _

- g.MeasureString((i).ToString, .Font).Width, y)

i += 1

Loop

g.DrawLine(Pens.SlateGray, LineNumbers.Width - 1, 0, LineNumbers.Width - 1, LineNumbers.Height)

'Debug.WriteLine("Finished: " & first_line + 1 & " " & i - 1)

End With

End Sub




Answer this question

How do I make this flicker-free?

  • Predator14567

    Turn the forms doublebuffer property on...

    Me.DoubleBuffer=True



  • MoPatel

    Where are you calling this function (DrawRichTextBoxLineNumbers) And how are you triggering the refresh of the main form

    Alex



  • oasisman

    More questions: Do you notice the flicker only when you scroll And when any edit is done, do you see multiple updates or a single one

    I'm not familiar with the double buffer property but from my understanding of how that would be implemented you may need to set it on every form and control beneath the picture box for it to work as expected. Also, it might only work properly if all drawing is done on paint events.

    Finally, you may want to only call the function on the paint events anyway, and invoke the refresh method to trigger the event whenever the text is changed or scrolled.

    If neither of these work, you can look into overriding the function OnPaintBackground for the form and picturebox to stop it from clearing the background under the picturebox, since that probably is what is causing the flicker.

    And that's the set of tricks I know about :)



  • BJHop

    Thank you very much for your help.

  • LISA86

    The line numbers flicker every time you type a character (because it not only draws the line numbers but it also highlights the current line).

    I have a feeling that i need to render everything to a Graphics object that's the same size as my PictureBox, then render the entire object into the PictureBox. This should eliminate flicker, but I have absolutely no idea how to implement it.



  • Thomas Greenleaf

    The function is called from a variety of different places, but they all call the function as follows:

    DrawRichTextBoxLineNumbers(LineNumbers.CreateGraphics)



  • Bahad&amp;#305;r KONU

    Thanks for your suggestion about setting the DoubleBuffered property to True, but it already is true and the drawing still flickers.

    The reason I needed to call the function from more than one place is because when the richtextbox is scrolled or the text is changed, the picturebox isn't invalidated, so it doesn't automatically get redrawn.

    Any more ideas



  • NG from NEMMCO

    In theory, that's what the doublebuffer property would do, but try this:

    Create a new bitmap object with the size you intend for the picturebox.

    Use the Graphics.FromImage method to get a graphics object that allows you to paint onto that bitmap

    Do the writing onto the bitmap

    Paint the bitmap into the picture box, or just remove the picture box and draw it directly into the form.



  • rguarino

    Why is it called from more than a place It seems to me that for something that shouldn't be animated, the function should be called only once, typically from the control's paint event. And whenever you make changes that should affect the drawing, you can cause a refresh of the control, instead of calling the function.

    Then again, I'm not a winforms specialist :)



  • How do I make this flicker-free?