Retrieve the Caret Position by Using an Extended TextBox Class

CodeGuru Editor's Comment: This article uses the Win32 API from C#. Generally, you should avoid calling such unmanaged code from a managed (.NET) application. This is, however, an interesting example of calling the API from .NET.

Sometimes, we need to know the caret position in a TextBox control; for example, in editor programs. The following ExtTextBox class extends the TextBox class with two read-only properties. The GetCaretXYPosition returns a Point struct with the (X,L) coordinates of the current position of the caret. The GetCaretLCPosition returns a CharPoint custom struct with the (L, C) coordinates of the position of the caret, where L is the one-based line number and C is the one-based column number.

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing;
namespace TextBoxUtils
   /// <summary>
   /// struct to handle the caret (L, C) co-ordinates
   /// L = one-based line number of the line containing the caret
   /// C = one-based column number in the line containing the caret
   /// </summary>
   public struct CharPoint
      private int l, c;

      public static readonly CharPoint Empty;

      static CharPoint()
         CharPoint.Empty = new CharPoint();

      public CharPoint(int l, int c)
         this.l = l;
         this.c = c;

      public override string ToString()
         return(String.Format("{{L={0}, C={1}}}", this.l, this.c));


   public class ExtTextBox: TextBox
      [DllImport("user32")] private static extern IntPtr
                            SendMessage(HandleRef hWnd, int msg,
                                        int wParam, int lParam);
      [DllImport("user32")] private static extern int
                            GetCaretPos(ref Point lpPoint);
      private int EM_LINEINDEX    = 0xbb;
      private int EM_LINEFROMCHAR = 0xc9;
      private int EM_GETSEL       = 0xb0;

      /// <summary>
      /// Gets the caret current (X, Y) position.
      /// </summary>
      /// <value>
      /// Point struct
      /// </value>
      public Point GetCaretXYPosition
            Point pt = Point.Empty;
            // get a Point struct with the caret current (X, Y)
            // position
            GetCaretPos(ref pt);
            // return the Point struct with the caret current
            // (X, Y) position
            return pt;

      /// <summary>
      /// Gets the caret current (L, C) position.
      /// </summary>
      /// <value>
      /// CharPoint struct
      /// </value>
      public CharPoint GetCaretLCPosition
            CharPoint cpt = CharPoint.Empty;
            // save the handle reference for the ExtToolBox
            HandleRef hr = new HandleRef(this, base.Handle );
            // Send the EM_LINEFROMCHAR message with the value of
            // -1 in wParam.
            // The return value is the zero-based line number 
            // of the line containing the caret.
            int l = (int)SendMessage(hr,EM_LINEFROMCHAR, -1, 0);
            // Send the EM_GETSEL message to the ToolBox control.
            // The low-order word of the return value is the
            // character position of the caret relative to the
            // first character in the ToolBox control,
            // i.e. the absolute character index.
            int sel = (int)SendMessage(hr, EM_GETSEL,0, 0);
            // get the low-order word from sel
            int ai  = sel & 0xffff; 
            // Send the EM_LINEINDEX message with the value of -1
            // in wParam.
            // The return value is the number of characters that
            // precede the first character in the line containing
            // the caret.
            int li = (int)SendMessage(hr,EM_LINEINDEX, -1, 0);
            // Subtract the li (line index) from the ai
            // (absolute character index),
            // The result is the column number of the caret position
            // in the line containing the caret.
            int c = ai - li;
            cpt = new CharPoint(l+1,c+1);
            // Add 1 to the l and c since these are zero-based.
            // Return a CharPoint with the caret current (L,C)
            // position
            return new CharPoint(l+1,c+1);



  • The Secret rule the mizuno-market Is Really Straightforward!

    Posted by Acuddence on 05/01/2013 11:33pm

    Beginner questions regarding nike have been answered and therefore the reasons you must absolutely read in detail each message of this story.[url=]ナイキ[/url] An actual double strain on nike [url=ゴルフボール-c-23.html]nikegolf[/url] Progressive questions on nike clarified and therefore why you must definitely view each term of this specific story. [url=アイアン-c-1.html]ゴルフ ナイキ[/url] Honest statement discloses Seven innovative new things on mizuno that not a soul is speaking of. [url=アイアン-c-1.html]ナイキ[/url] A nike Commerce Dialog - Which means, who cares is the winner?! [url=ゴルフシューズ-c-15.html]nike dunk[/url] Supplies and assembly throughout Michigan -- nike will leave without cheers [url=]ナイキ スニーカー[/url] Goods and show in Las Vegas, Nevada - mizuno actually leaves without good-bye [url=ナイキRunning-c-3.html]nike running[/url] Some of the nike Company Dialog -- Those who cares gains all the rewards? [url=ナイキDunk-c-9.html]ナイシューズ[/url] A nike Sector Dialog : Customers who cares about fears benefits?! [url=ナイキDunk-c-9.html]nike dunk[/url] mizuno offers fresh, new lifespan to a old matter. . . defacto requirements

  • Observation

    Posted by webmasta on 05/05/2005 10:06pm

    Excellent results with the caret co-ordinates! For the line and col: #1: Erroneous results with wordwrap on. #2: Counts a tab space as one column.

  • Why this article was passed

    Posted by darwen on 11/21/2004 06:57pm

    Your comments were viewed by myself in the reviewer's forum. However, I considered this article to have useful areas (e.g. the use of HandleRef) which made it worthwhile publishing. Yes, there are alternative methods to do this but this demonstrates .NET classes which people might not be aware of, and as such was published.

  • This seems like overkill

    Posted by gregoftheweb on 10/15/2004 12:16pm

    Internet Explorer exposes the caret position of TextArea's natively. This can all be accomplished on the client with no round trip to the server. If you eventually need the carret position you can pass the position by itself back to the application.

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As businesses have grown in size and global reach, emerging technologies such as cloud computing and virtualization have appeared to help companies effectively connect and grow. However, the networking strategies and infrastructures that keep organizations connected have often remained in the past. Now, new strategies that leverage global connectivity and locations exist to provide a more flexible and cost-effective alternative to traditional networking systems. This Aberdeen report analyzes how top performing …

  • On-demand Event Event Date: March 27, 2014 Teams need to deliver quality software faster and need integrated agile planning, task tracking, source control, auto deploy with continuous builds and a configurable process to adapt to the way you work. Rational Team Concert and DevOps Services (JazzHub) have everything you need to build great software, integrated seamlessly together right out of the box or available immediately in the cloud. And with the Rational Team Concert Client, you can connect your …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds