Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / VB

.NET Get Correct Caret Position from TextBox Control

5.00/5 (1 vote)
8 Jul 2014CPOL2 min read 16.1K  
How to get correct caret position from Textbox control

Introduction

If you do an Internet search for something like '.NET textbox caret position', most of the suggestions you will get are to use GetPositionFromCharIndex and pass in the SelectionStart value. This works as long as the caret is not at the end. If the caret is at the end, it always returns Point.Empty (0,0).

Background

I ran across this problem when trying to figure out how to position a help message next to a textbox.

If you use a reflector on the .NET framework, and view the code at System.Windows.Forms.TextBoxBase.GetPositionFromCharIndex(), you will see at the beginning of the function:

C#
if (index < 0 || index >= this.Text.Length)
{
   return Point.Empty;
}

So with your TextBox control, you call TextBox1.GetPositionFromCharIndex(TextBox1.SelectionStart) you will get Point.Empty anytime SelectionStart is at the end (Internet Explorer, the user adding text and the caret is at the end of the content).

If the caret position is not at the beginning or end, then the .NET TextBoxBase will send a Windows message with an ID 214 to retrieve the position.

While still in a reflector, if you go over to System.Windows.Forms.RichTextBox.GetPositionFromCharIndex(), you will see something like:

C#
if (index < 0 || index > this.Text.Length)
{
   return Point.Empty;
}

Note that this differs only by index >= this.Text.Length versus index > this.Text.Length. The code also sends out a Windows message with an ID 214 to retrieve the position.

Using the Code

You can do it the same way in the reflector, by sending your own Windows message, or you can use the GetCaretPos function in the User32.dll to get the position back. This method is considerably simpler in my opinion.

For instance, in C#, it would be:

C#
[DllImport("user32.dll")]
private static extern bool GetCaretPos(out Point lpPoint);

public Point GetCorrectCaretPos()
{
    Point pt = Point.Empty;
    if (GetCaretPos(out pt))
    {
        return pt;
    }
    else
    {
        return Point.Empty;
    }
}

For VB.NET, it would be:

VB.NET
<DllImport("user32.dll")> _
Private Shared Function GetCaretPos(ByRef lpPoint As Point) As Boolean
End Function

Public Function GetCorrectCaretPos() As Point
    Dim pt As Point = Point.Empty
    If GetCaretPos(pt) Then
        Return pt
    Else
        Return Point.Empty
    End If
End Function

Points of Interest

I found it interesting that Microsoft fixed it for the RichTextBox control but not the TextBox control.

License

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