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 Singlefont_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 Integerfirst_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 RichTextBoxg.Clear(LineNumbers.BackColor)
Dim i As Integer = first_line Dim y As Single Do While y < g.VisibleClipBounds.Y + g.VisibleClipBounds.Heighty = first_line_y + 2 + font_height * (i - first_line - 1) - 2
If i = RichTextBox1.GetLineFromCharIndex(RichTextBox1.SelectionStart) + 1 Theng.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 Ifg.DrawString((i).ToString, .Font, Brushes.SlateGray, LineNumbers.Width _
- g.MeasureString((i).ToString, .Font).Width, y)
i += 1
Loopg.DrawLine(Pens.SlateGray, LineNumbers.Width - 1, 0, LineNumbers.Width - 1, LineNumbers.Height)
'Debug.WriteLine("Finished: " & first_line + 1 & " " & i - 1) End With End Sub
How do I make this flicker-free?
Derol
The function is called from a variety of different places, but they all call the function as follows:
DrawRichTextBoxLineNumbers(LineNumbers.CreateGraphics)
DMillerNCR
Where are you calling this function (DrawRichTextBoxLineNumbers) And how are you triggering the refresh of the main form
Alex
Deepesh Verma
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 :)
AndyPham
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.
Chris128
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
anderskj1
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 :)
Matt Ellis
estrela666
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.
RufusLDK
Turn the forms doublebuffer property on...
Me.DoubleBuffer=True