Click here to Skip to main content
15,868,135 members
Articles / Multimedia / GDI+

Line Numbering of RichTextBox in .NET 2.0

Rate me:
Please Sign up or sign in to vote.
4.07/5 (17 votes)
26 Jan 2007CPOL2 min read 131.9K   2.6K   52   23
Line numbering of a RichTextBox control using PictureBox control painting.

Sample Image - sample.jpg

Introduction

This article demonstrates how to add line numbers to a RichTextBox control. This is done by adding a PictureBox control on the left side of the rich text box control. When the appropriate events happen on the Form or on the RichTextBox control, we call a method that paints the line numbers on the PictureBox control. This approach is more accurate and efficient than other approaches I've seen where another textbox control is used for printing the line numbers. The PictureBox will only print the line numbers that are currently visible in the RichTextBox control. During the process of constructing this code sample, I initially based it on the code sample provided in the article: http://www.codeproject.com/cs/miscctrl/numberedtextbox.asp and enhanced it by doing the following:

  1. Replace the Label control for numbering with a PictureBox.
  2. I fixed the scrolling problem with that implementation due to the fact that the RichTextBox uses smooth scrolling (scrolling with the scrollbar scrolls the text in pixels, not in lines). As a result, sometimes the first line may be displayed in half, in which case, the line numbering should address it.

Here is the code for printing the line numbers. Note that we have a RichTextBox control called MyRichTextBox and a PictureBox control called MyPictureBox. The method gets an argument which is the Graphics of the PictureBox control. This is the method DrawRichTextBoxLineNumbers:

VB
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 MyRichTextBox
   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(Control.DefaultBackColor)
   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)
    g.DrawString((i).ToString, .Font, Brushes.DarkBlue, MyPictureBox.Width _
          - g.MeasureString((i).ToString, .Font).Width, y)
    i += 1
   Loop
   'Debug.WriteLine("Finished: " & firstLine + 1 & " " & i - 1)
  End With
End Sub

This method should be called from the following locations:

  1. Upon RichTextBox's Resize event: DrawRichTextBoxLineNumbers(MyPictureBox.CreateGraphics).
  2. When the VScroll event happens on the RichTextBox: (MyRichTextBox.VScroll).DrawRichTextBoxLineNumbers(MyPictureBox.CreateGraphics).
  3. When the Paint event happens: (MyPictureBox.Paint).DrawRichTextBoxLineNumbers(e.Graphics). Note that it this method, we send e.Graphics and not MyPictureBox.CreateGraphics, as we would like to repaint only the required region within the PictureBox control.

These are the locations from which we need to invoke the line numbering method:

VB
Private Sub r_Resize(ByVal sender As Object, ByVal e As System.EventArgs) _
     Handles MyRichTextBox.Resize
     MyPictureBox.Invalidate()
End Sub

Private Sub r_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles MyRichTextBox.VScroll
  MyPictureBox.Invalidate()
End Sub

Private Sub p_Paint(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.PaintEventArgs) _
        Handles MyPictureBox.Paint
  DrawRichTextBoxLineNumbers(e.Graphics)
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles MyBase.Load
  MyRichTextBox.Text = vbCrLf & vbCrLf & vbCrLf
End Sub

Other general notes

  1. The code above assumes that the font name and the size of the RichTextBox control is the same for the entire text.
  2. The WordWrap property of the RichTextBox control should be set to False.
  3. I've placed this code in the Form_Load method to assure that the textbox has at least two lines always:
  4. VB
    MyRichTextBox.Text = vbCrLf & vbCrLf & vbCrLf
  5. I recommend docking the PictureBox to the left and then calculating the width of the PictureBox based on g.MeasureString("000", MyRichTextBox.Font).Width. The width of the PictureBox should be recalculated, and the PictureBox should be redrawn when the font of the RichTextBox changes.
  6. The PictureBox control may be replaced with a Panel or any other control that exposes the CreateGraphics() method.
  7. The control was designed for RichTextBox controls with WordWrap = False.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
Questionline width Pin
CodeMine13-May-20 15:25
CodeMine13-May-20 15:25 
BugYou saved me hours! Pin
LLLLGGGG23-May-12 8:05
LLLLGGGG23-May-12 8:05 
GeneralRe: You saved me hours! Pin
Eki Indradi22-Dec-15 4:47
Eki Indradi22-Dec-15 4:47 
QuestionHi Pin
Botsbushman11-Aug-08 13:09
Botsbushman11-Aug-08 13:09 
GeneralThanks Pin
Mohammad Dayyan6-May-08 8:51
Mohammad Dayyan6-May-08 8:51 
GeneralProblem with moving thumb Pin
Dipendu Paul5-Jul-07 1:18
Dipendu Paul5-Jul-07 1:18 
GeneralSimple code modifications Pin
Jason Barrera22-Jun-07 11:55
Jason Barrera22-Jun-07 11:55 
QuestionText Change in coordinate with font changes... Pin
brottmayer22-Feb-07 3:10
brottmayer22-Feb-07 3:10 
GeneralLine numbering in C# - complete [modified] Pin
biopsy15-Feb-07 5:44
biopsy15-Feb-07 5:44 
GeneralRe: Line numbering in C# - complete [modified] Pin
Panki_17-Oct-11 22:32
Panki_17-Oct-11 22:32 
GeneralLooks great Pin
Alexandru Lungu30-Jan-07 10:08
professionalAlexandru Lungu30-Jan-07 10:08 
GeneralHi Pin
Ahmed El-Badry25-Jan-07 1:47
Ahmed El-Badry25-Jan-07 1:47 
GeneralResource leak due to CreateGraphics Pin
mav.northwind25-Dec-06 22:01
mav.northwind25-Dec-06 22:01 
GeneralRe: Resource leak due to CreateGraphics Pin
Michael Elly26-Jan-07 0:27
Michael Elly26-Jan-07 0:27 
QuestionAny way to make the code show line numbers only upto contained lines in the RTBox? Pin
kil0byte^bandit5-Dec-06 4:37
kil0byte^bandit5-Dec-06 4:37 
AnswerRe: Any way to make the code show line numbers only upto contained lines in the RTBox? Pin
Michael Elly6-Dec-06 20:19
Michael Elly6-Dec-06 20:19 
GeneralRe: Any way to make the code show line numbers only upto contained lines in the RTBox? Pin
gabegabe4-Jan-07 4:20
gabegabe4-Jan-07 4:20 
GeneralRe: Any way to make the code show line numbers only upto contained lines in the RTBox? Pin
Michael Elly26-Jan-07 0:43
Michael Elly26-Jan-07 0:43 
Generalwordwrap linecount fix Pin
gabegabe17-Jan-07 21:29
gabegabe17-Jan-07 21:29 
General[Message Deleted] Pin
Arkady Lesniara26-Jun-06 4:24
Arkady Lesniara26-Jun-06 4:24 
GeneralRe: Compile Problem Pin
Andy Davies26-Jun-06 6:27
Andy Davies26-Jun-06 6:27 
GeneralRe: Compile Problem Pin
Michael Elly27-Jun-06 6:43
Michael Elly27-Jun-06 6:43 
GeneralRe: Compile Problem Pin
Arkady Lesniara27-Jun-06 6:54
Arkady Lesniara27-Jun-06 6:54 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.