RSS 2.0 Feed
RSS 2.0


Atom 1.0 Feed
Atom 1.0

  Counting the number of lines in a TextBox 


A while back I helped a friend with determining how to count the number of lines contained in the TextBox. He needed to count each line - whether it was a line wrapped from the line above it, or from a carriage return to start a new line. The problem is that most ways to count lines in a TextBox will only count actual new lines, or lines that are a result of a carriage return. Not the lines as the result from a line wrap as these are not typically seen as their own lines. Also, if the TextBox is resized, then the line count needs to refect the number of lines at that moment.

Not a difficult task, however, it does require a bit of magic ala Windows messages. To make this as clean as possible, let's just inherit from TextBox to give it a new property to get the number of lines displayed in the TextBox. While we are at it, let's add properties for LineIndex and LineLength so we can determine the lenth of a given line. Exposing the LineIndex will allow us to loop through the lines in the TextBox. We'll use the EM_GETLINECOUNT message to retrieve the number of lines in the TextBox, the EM_LINEINDEX message to get the index of a line and EM_LINELENGTH to get the length of a given line. Then all we'll need to do is wrap these up in a messages and pump them off to Windows via the base TextBox's DefWndProc method. Take a look at the complete & new TextBox control:


using System;
using System.Windows.Forms;

namespace TextBoxLines
{
    public class TextBoxEx : TextBox
    {
        private const int EM_GETLINECOUNT = 0xBA;
        private const int EM_LINEINDEX = 0xBB;
        private const int EM_LINELENGTH = 0xC1;

        public TextBoxEx() :base()
        {
            //Since we'll want multiple lines allowed we'll add that to the constructor
            this.Multiline = true;
            this.ScrollBars = ScrollBars.Vertical;
        }

        public int LineCount
        {
            get
            {
                Message msg = Message.Create(this.Handle, EM_GETLINECOUNT, IntPtr.Zero, IntPtr.Zero);
                base.DefWndProc(ref msg);
                return msg.Result.ToInt32();
            }
        }

        public int LineIndex(int Index)
        {
            Message msg = Message.Create(this.Handle, EM_LINEINDEX, (IntPtr)Index, IntPtr.Zero);
            base.DefWndProc(ref msg);
            return msg.Result.ToInt32();
        }

        public int LineLength(int Index)
        {
            Message msg = Message.Create(this.Handle, EM_LINELENGTH, (IntPtr)Index, IntPtr.Zero);
            base.DefWndProc(ref msg);
            return msg.Result.ToInt32();
        }
    }
}

Just beautiful. Now you have them built into the TextBox. Use them just as you would use any property for the TextBox and get the number of lines displayed in the TextBox - doesn't matter if they are wrapped lines or actual lines. You can download this code in a sample project below.

 TextBoxLines sample project




                   



Leave a comment below.

Comments

  1. MK 6/25/2004 7:06 AM
    Gravatar
    Thank you for the excellent code. I didn't know about these Windows messages and this is just what I was looking for. :)
  2. chw 11/4/2004 12:20 AM
    Gravatar
    Excellent item - concise and to the point ...
  3. Segato 1/14/2005 2:01 AM
    Gravatar
    This is just brilliant been looking for something like this for a long time!
  4. Harri 1/29/2005 4:36 AM
    Gravatar
    I'd like to see row lines on the left side of TextBox.
    How can I synchronize for example uiRowLine and uiTextBox.
    I have tried to mix your example and EM_GETFIRSTVISIBLELINE,
    but I don't know how send that message to uiRowLine.
  5. Jesus 11/25/2005 1:55 AM
    Gravatar
    Simple, clear and useful. Thank you very much!

    Greetings from Huesca, Spain
  6. Julien Lembo 1/19/2007 1:15 PM
    Gravatar
    With Framework 2.0 it's simple :

    textBox1.Lines.Length
  7. Carolina 1/22/2007 8:56 AM
    Gravatar
    I'm trying to use this code for a webpage and I got some errors do you have this code for WEB.
    thanks
  8. Ryan Farley 1/22/2007 9:00 AM
    Gravatar
    Carolina,

    The code in this post is not meant for web and will definitely not work in a web environment.
  9. Mr. Bungle 4/9/2007 12:53 AM
    Gravatar
    Top work Ryan. Note to others: It's not necessary to set the ScrollBars property to Vertical in the TextBoxEx constructor, as this will work whether scrollbars are visible or not.
  10. Mohammed 7/16/2007 10:08 AM
    Gravatar
    Does anyone know how to do the same thing for web?
  11. Mikael 8/20/2007 5:25 PM
    Gravatar
    Wonderful, i was looking for just this. I was trying to use TextRenderer.MeasureString but the formating flags didn't contain any choice regardnig wordwrap. I was hoping to get the desired height and specifying a fixed width and then divide that by the font's height. But of course since the formatting flags didn't contain what i wanted this proved to be a wonderful solution.
  12. Muhammad Rauf 1/1/2008 4:57 AM
    Gravatar
    This thing I am serching for many days. Can any one tell more messages about like;
    current line of the current caret(cursor),
    jump to a specified line no,
    etc.

    Thanks
  13. Dmitry Boyko 3/5/2008 10:52 AM
    Gravatar
    Yes!!! Thanks, amigo!
  14. sbing 1/3/2009 11:20 PM
    Gravatar
    Thanks, this is just what I was looking for!
  15. Rudolf 3/27/2009 5:18 AM
    Gravatar
    Excelent, thanks :)
  16. Ozzy 6/3/2009 12:08 PM
    Gravatar
    Is there anyway to convert this to RichTextBox?

    And im a little lost on how to use it, do you put it in a class file and call it like so:

    this.textBox1.LineCount; ?
  17. Ozzy 6/3/2009 12:08 PM
    Gravatar
    Is there anyway to convert this to RichTextBox?

    And im a little lost on how to use it, do you put it in a class file and call it like so:

    this.textBox1.LineCount; ?
  18. Ozzy 6/3/2009 12:08 PM
    Gravatar
    Is there anyway to convert this to RichTextBox?

    And im a little lost on how to use it, do you put it in a class file and call it like so:

    this.textBox1.LineCount; ?
  19. Mitch 10/19/2009 6:18 AM
    Gravatar
    Cool code. I converted it to VB using the convertor at developerfusion and there was an issue converting an IntPtr to an Integer. Which led me to come up with this little morsel.

    'You can do it the long way
    'Dim x As IntPtr
    'Dim y As Integer = -1
    'x = New IntPtr(y)

    ' or instead use the following
    'Dim x as IntPtr;
    'Dim y as Integer = 1337;
    'x = IntPtr.op_Explicit(y) 'this is an undocumented feature

    Public Function LineIndex(ByVal Index As Integer) As Integer
    Dim x As IntPtr = IntPtr.op_Explicit(Index)
    'Dim msg As Message = Message.Create(Me.Handle, EM_LINEINDEX, DirectCast(Index, IntPtr), IntPtr.Zero)
    Dim msg As Message = Message.Create(Me.Handle, EM_LINEINDEX, x, IntPtr.Zero)
    MyBase.DefWndProc(msg)
    Return msg.Result.ToInt32()
    End Function

    Anyways, cheers.
    Mitch
  20. canahari 5/23/2010 9:57 AM
    Gravatar
    Dear all,

    I'm trying to count the maximum number of lines which can be added to a textbox of a given size without a scrollbar appearing. Does anyone have an idea about this?

    Can you give me a clue where can I read more about these messages? This solution is very nice and maybe it could be used for other things too :)

  21. 7/7/2012 6:13 AM
    Gravatar
    Autofit WinForms RichTextBox to its contents | mywebsite
  22. 7/6/2014 8:08 AM
    Gravatar
    [RESOLVED]Textbox – Count the Number of Lines | ASP Web Form Data Control
Comments have been closed on this topic.



 

News


Also see my CRM Developer blog

Connect:              


Sponsor

Sections