Click here to Skip to main content
Click here to Skip to main content

Line Numbers for RichText Control in C#

, 11 Aug 2009
Rate this:
Please Sign up or sign in to vote.
Display line numbers for rich text box with auto sizing. This is a converted version from another article written in VB.NET.

Introduction

Please wait while more details are being updated.

This article is a converted project from VB.NET to C#, originally created by nogChoco in the article, "LineNumbers for the RichTextBox".

Sure anyone can make a line numbering user control.  I've made many variations of them for VB 3.0 to 6.0 & C++, always using picture boxes or whatever as a drawing base to mark the position. When Microsoft released the newer versions of RichText control boxes (in more recent versions), the old methods went out the door.  By this, I mean that one can easily zoom in & out of the box by holding down Ctrl (or Shift) key while using the mouse wheel, posing a HUGE problem for traditional methods. 

Q: Why use RichText instead of the traditional TextBox?
A: (In older versions) RichText can hold more data! (and offers more features)

LineNumbers.png

Before Compiling Fore-note  

I have successfully compiled & ran this example project under both Visual Studio 2008 & SharpDevelop 3.x using Framework 2.0.

You will probably have problems running this example project under VS 2005 & lower; do note the control does work under the Framework 2.0If you are having problems running this under VS 2005 or other studios, you might want to either find yourself a project converter or upgrade your studio. I am very sorry if this is an inconvenience for you, that is why this is posted for Intermediate & Expert users. 

If you want a free IDE that can run this, try out SharpDevelop IDE.

Compiling Your Own Project

LineNumbers_-_ex3.png

Using SharpDevelop (3.x) 

  1. Create a new C# Windows project
  2. Add Reference to your project (Right click 'References' > 'Add Reference')
  3. Under GAC Tab select: "Microsoft.VisualBasic"
  4. Insert into your project existing item.. "linenum_rtf.cs"
  5. Under Custom Components, insert "LineNumbers_For_RichTextBox" into your form as well as insert a RichTextBox
  6. Line them up side by side (left side by default)
  7. Link Line Numbers to your RichTextBox
    1. Under "Add LineNumbers to" > "Parent Rich Text Box":
    2. Select your RichTextBox to add line numbers to
    3. (feel free to customize it on your own)
  8. Run the project!

Using Visual Studio (2008)

  1. Create a new C# Windows Project
  2. Add Reference to your project (Right click 'References' > 'Add Reference')
  3. Under .NET Tab select: "Microsoft.VisualBasic"
  4. Insert the existing item into your project... "linenum_rtf.cs"
  5. Build your project!
    1. This will not show under Custom Components unless you build you the project first!
  6. Under Custom Components, insert "LineNumbers_For_RichTextBox" into your form as well as insert a RichTextBox
  7. Line them up side by side (left side by default)
  8. Link Line Numbers to your RichTextBox
    1. Under "Add LineNumbers to" > "Parent Rich Text Box":
    2. Select your RichTextBox to add line numbers to
    3. (feel free to customize it on your own)
  9. Run the project!

Background and Points of Interest

As a software designer/developer like all of you, time is of the essence when meeting deadlines! This example using the RichText control works great! Especially with the zoom in/out feature using the mouse wheel, and it added nice graphical features which can be easily customized. However, I feel the urging need to program in C# and this example was only provided in VB.NET... It was time to upgrade it & now, on with the show!

History

  • 2009.08.05 - Initial conversion from VB.NET to C#
  • 2009.08.08 - Updated notes on this page (pictures soon to come)

To Do

  • Provide 2 versions
    • Graphical: The current version (customizable and beautiful)
    • Simple: Side bar is simple & has low overhead on your projects
  • Strip out references to Microsoft.VisualBasic so it's more pure C#

- Damian J. Suess of Xeno Innovations, Inc. [2000-2009]

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)

About the Author

Damian J. Suess
CEO Xeno Innovations, Inc.
United States United States
[ Exceeding the Limits of Imagination ]

Comments and Discussions

 
QuestionGood PinmemberElegiac19-May-13 21:45 
AnswerRe: Good PinmemberDamian J. Suess3-Jun-13 11:17 
QuestionVisual Studio 11 support Pinmemberverber0017-Jun-12 17:11 
AnswerRe: Visual Studio 11 support PinmemberDamian J. Suess3-Jun-13 11:14 
GeneralMy vote of 5 PinmemberPanki_17-Oct-11 20:36 
Generalstatic 'Main' method not suitable for an entry point Pinmember501st_commander26-Apr-10 10:10 
QuestionLicense??? PinmemberTannner.R9-Apr-10 13:18 
AnswerRe: License??? PinmemberDamian J. Suess10-Apr-10 7:02 
GeneralRe: License??? PinmemberTannner.R10-Apr-10 7:10 
GeneralRe: License??? PinmemberTannner.R5-May-10 8:41 
GeneralOne more thing - if you want to solicit input and maintain changes... PinmemberCheeso31-Mar-10 13:25 
Questionline numbers disappear when the # of lines is large? PinmemberCheeso31-Mar-10 13:23 
AnswerRe: line numbers disappear when the # of lines is large? PinmemberDamian J. Suess10-Apr-10 7:05 
GeneralRe: line numbers disappear when the # of lines is large? PinmemberCheeso20-Apr-10 4:14 
BugRe: line numbers disappear when the # of lines is large? PinmemberHirnhamster16-Jan-12 2:10 
QuestionI cant find the control PinmemberAlexanderBorup27-Feb-10 13:50 
AnswerRe: I cant find the control PinmemberDamian J. Suess28-Feb-10 8:24 
Generalsome mod's to make it a bit more c#: PinmemberRob24121-Jan-10 21:38 
GeneralRe: some mod's to make it a bit more c#: PinmemberDamian J. Suess2-Jan-10 5:22 
QuestionWhen it is a lot of lines Pinmemberrave4ka5-Oct-09 7:31 
AnswerRe: When it is a lot of lines PinmemberDamian J. Suess2-Jan-10 5:21 
GeneralRe: When it is a lot of lines PinmemberCheeso31-Mar-10 13:16 
I looked into this as well. Found that the TextChanged() method gets called very very often. I had coupled this with a RTB that was displaying XML, and also formatting the XML with syntax highlighting. With every format change, the zParent_Changed method was being invoked, which then invalidated the control and caused a repaint.
 
That didn't work out so well. Definitely need a way to distinguish between types of changes and be more intelligent about re-painting. It's possible you could use a backoff timer. If you get 72 zParent_Changed() calls in a row, wait.... until they stop coming. And only do the refresh/invalidate after a short delay when no further zParent_Change events occur. Haven't tested this, it's only an idea.
 
The other thing: inside Update_VisibleLineNumberItems(), there are a number of things that can be easily optimized. For one thing, every retrieval of zParent.Text is expensive. So, retrieve it once at the top of the method and replace all zParent.Text with a reference to the local copy. Like this:
 
    if (zParent == null)
        return;
 
    string txt = zParent.Text; // getting the text is expensive. We do it once.

    if (string.IsNullOrEmpty(txt))
        return;
    ...
 
For another thing, the timer in that method is sort of odd. It's very simple to replace it with a stopwatch. Not sure if that's a performance thing, but it makes the code cleaner.
 
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    ....
 
        if (zParentIsScrolling == true && stopwatch.ElapsedMilliseconds > 500)
        {
 
 
Finally, counting the lines is done via a call to String.Split() , which produces an array of strings. Then the .Length property is retrieved on that array.
 
   zSplitStartLine = Math.Max(0, zParent.Text.Substring(0, zStartIndex).Split("\r\n".ToCharArray()).Length - 1);
 

This is very inefficient, if all you want to know is how many \n characters are in the string. Replace that with a simple utility method that iterates through the chars of the string.
 
  private static int CountNewlines(string s)
  {
      int len = s.Length;
      int c = 0;
      for (int i=0; i < len;  i++)
      {
          if (s[i] == '\n') c++;
      }
      return c+1;
  }
 
  ...
 
    zSplitStartLine = Math.Max(0, CountNewlines(txt.Substring(0, zStartIndex)) - 1);
 
 
With these changes, the control is much more usable for me for RTB's with larger content.
 

Thanks for the control, though. Very very useful.
QuestionRe: When it is a lot of lines PinmemberPanki_17-Oct-11 20:27 
Generalvery good. PinmemberZielonekk4-Sep-09 0:01 
GeneralGet the line number when clicking on the control Pinmemberkenneth_cwc22-Aug-09 5:54 

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

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

| Advertise | Privacy | Mobile
Web03 | 2.8.140709.1 | Last Updated 11 Aug 2009
Article Copyright 2009 by Damian J. Suess
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid