我需要知道我的窗口中插入符号当前所在位置的确切位置,以便我可以在文本下方弹出一个小窗口(类似于智能感知或拼写检查)。问题是GetPositionFromCharIndex似乎不适用于TextBoxes。这就是我想要做的事情:
Point pt = mTextBox.GetPositionFromCharIndex(mTextBox.SelectionStart);
pt.Y = (int)Math.Ceiling(mTextBox.Font.GetHeight());
mListBox.Location = pt;
但是,GetPositionFromCharIndex总是为TextBoxes返回(0,0)(显然它没有像RichTextBox那样实现)。虽然这个函数(和这个代码)适用于RichTextBoxes,但我不希望将我的其余代码从TextBox迁移到RichTextBox,除非是绝对的 LAST 。与RichTextBox / TextBox有很多不兼容的地方,我必须重写一段非常的大部分代码才能做到这一点。
是否有任何Winforms巫师知道如何做到这一点?
答案 0 :(得分:7)
如果您不介意使用Win32-API,请使用GetCaretPos获取确切位置。
答案 1 :(得分:5)
我发现了文本框控件的一些特殊行为。当您在文本框的末尾键入文本时,GetPositionFromCharIndex仍为0,0。但是,如果在文本框中的最后一个字符之前插入文本,则会更新GetPositionFromCharIndex。
不知道你是否可以利用它,但我想你可能想知道这一点。
编辑:好的,大声笑,这似乎有效,可能有多丑......:
Point pt = textBox1.GetPositionFromCharIndex(textBox1.SelectionStart > 0 ? textBox1.SelectionStart - 1 : 0);
编辑2:回想起来,我认为行为并不那么奇怪,因为文本框末尾的SelectionStart会返回下一个字符将被输入的索引,而不是最后一个字符的实际位置。由于GetPositionFromCharIndex将返回一个字符位置,因此尚未存在的char的索引显然返回0,0。
编辑3:随着我和MikeJ的代码相结合并略微重新设计,你可以得到插入符号的确切位置:
SizeF size = g.MeasureString(textBox1.Text.Substring(textBox1.SelectionStart - 1, 1), textBox1.Font);
pt.X += (int)size.Width;
我承认,我输入它的方式真是太棒了,但是通过一些编辑,你应该可以从中获得一些不错的代码。
答案 2 :(得分:1)
在TextBox.KeyDown
事件中附加以下代码段,以便在文本框控件中找到光标的屏幕点:
using (Graphics g = Graphics.FromHwnd(textBox1.Handle))
{
SizeF size = g.MeasureString(textBox1.Text.Substring(0, textBox1.SelectionStart), textBox1.Font);
Point pt = textBox1.PointToScreen(new Point((int)size.Width, (int)0));
label1.Text = "Manual: " + pt.ToString();
}
上面的代码片段考虑了TextBox
控件使用的字体,以正确计算字符串的实际长度,直到控件中的光标位置。执行“智能感知”样式的自动完成弹出窗口时,了解实际屏幕位置以弹出“自动完成”列表非常重要。
这就是代码片段的作用。它计算文本的宽度,然后将其转换为“本地”坐标到TextBox控件,并从那里将该点转换为相关的屏幕坐标。
需要注意的一点需要注意:SelectionStart
已延迟且未立即更新。这部分是由于文本框控件如何处理键盘输入。
答案 3 :(得分:0)
TextBox lbl = new TextBox();
lbl.Text = Build("20000", i);
lbl.Location = new Point(30, 25 * i);
lbl.Width = 350;
lbl.MouseHover += new EventHandler(lbl_MouseHover);
void lbl_MouseHover(object sender,
EventArgs e)
{
TextBox t = (TextBox)sender;
ListBox lb = new ListBox();
for (int i = 0; i < 10; i++)
{
lb.Items.Add("Hej");
}
int x = t.Location.X;
int y = t.Location.Y + t.Height;
lb.Location = new Point(x, y);
panel1.Controls.Add(lb);
lb.BringToFront();
}
请注意这段特殊代码: int y = t.Location.Y + t.Height; 您将文本框的高度添加到y轴。
答案 4 :(得分:0)
MessageBox.Show(textBox1.SelectionStart.ToString());
答案 5 :(得分:0)
试试这个。
在`Control.KeyPress`事件下,
我使用Control.GetPositionFromCharIndex(Control.SelectionStart)
来获取与控件相关的插入位置。然后翻译此位置与表格新位置的屏幕相关。
private void aTextBox_KeyPress(object sender, KeyPressEventArgs e)
{
SuperComboForm supcomboF = new SuperComboForm();
supcomboF.StartPosition = FormStartPosition.Manual;
var caret_pos = aTextBox.GetPositionFromCharIndex(aTextBox.SelectionStart);
supcomboF.Location = PointToScreen(new Point(caret_pos.X, caret_pos.Y));
supcomboF.ShowDialog();
}
答案 6 :(得分:0)
这是我的解决方法:
private Point GetCaretPosition()
{
Point result = TextBox.GetPositionFromCharIndex(TextBox.SelectionStart);
if (result.X == 0 && TextBox.Text.Length > 0)
{
result = TextBox.GetPositionFromCharIndex(TextBox.Text.Length - 1);
int s = result.X / TextBox.Text.Length;
result.X = (int)(result.X + (s * 1.3));
}
return result;
}