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:
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:
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:
[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:
<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.