知道Winforms TextBox中插入符号的点位置?

时间:2009-12-02 07:36:10

标签: c# winforms

我需要知道我的窗口中插入符号当前所在位置的确切位置,以便我可以在文本下方弹出一个小窗口(类似于智能感知或拼写检查)。问题是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巫师知道如何做到这一点?

7 个答案:

答案 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;
}