Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knowing the point location of the caret in a Winforms TextBox?

Tags:

c#

winforms

I need to know the exact point location in my window where the caret currently resides so that I can pop up a small window under the text (similar to intellisense or a spellchecker). The issue is that GetPositionFromCharIndex doesn't seem to work on TextBoxes. This is what I'm trying to do:

Point pt = mTextBox.GetPositionFromCharIndex(mTextBox.SelectionStart);
pt.Y = (int)Math.Ceiling(mTextBox.Font.GetHeight());
mListBox.Location = pt;

However, GetPositionFromCharIndex always returns (0, 0) for TextBoxes (apparently it isn't implemented like it is for RichTextBox). While this function (and this code) works fine for RichTextBoxes, I don't want to migrate the rest of my code from TextBox to RichTextBox except as an absolute LAST resort. There are so many incompatibilities with RichTextBox/TextBox that I'll have to rewrite a very large chunk of my code to do this.

Are there any Winforms wizards out there who know how to do this?

like image 693
LCC Avatar asked Dec 02 '09 07:12

LCC


2 Answers

If you don't mind using Win32-API use GetCaretPos to get the exact position.

like image 59
J. Random Coder Avatar answered Sep 23 '22 10:09

J. Random Coder


I have discoverd some peculiar behavior of the textbox control. When you type text at the end of the textbox, GetPositionFromCharIndex remains 0,0. However, if you insert text before the last char in the textbox, GetPositionFromCharIndex IS updated.

Don't know if you can use that to your advantage, but I think you might wanted to know that.

Edit: Ok, LOL, this seems to work, how ugly it may be...:

Point pt = textBox1.GetPositionFromCharIndex(textBox1.SelectionStart > 0 ? textBox1.SelectionStart - 1 : 0);

Edit 2: In retrospect, I think the behavior isn't so odd, since the SelectionStart at the end of a textbox returns the index where the next character will be typed, not where the last character actually is. Since GetPositionFromCharIndex will return an character position, the index of a not yet existing char returns apparently 0,0.

Edit 3: With mine and MikeJ's code combined and slightly reworked, you can get the exact position of the caret:

SizeF size = g.MeasureString(textBox1.Text.Substring(textBox1.SelectionStart - 1, 1), textBox1.Font);
pt.X += (int)size.Width;

I admit, It's damn-ugly the way I typed it, but with some editing you should be able to get some nice code out of this.

like image 26
Webleeuw Avatar answered Sep 22 '22 10:09

Webleeuw