GetCharIndexFromPosition()获取最后一个字符
本文关键字:最后一个 字符 获取 GetCharIndexFromPosition | 更新日期: 2023-09-27 18:12:27
我想在RichTextBox中获得光标下的子字符串。
private void richTextBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Clicks == 1 && e.Button == MouseButtons.Left)
{
string wholeText = richTextBox1.Text;
// Obtain the character index where the user clicks on the control.
int positionBegin = richTextBox1.GetCharIndexFromPosition(new Point(e.X, e.Y));
SelectedText = wholeText.Substring(positionBegin);
}
例如,如果我键入字符串World
,然后将光标放在l
和d
之间,则子字符串应该是d
。到目前为止,我的代码是工作的,但是如果我把光标放在字符串的末尾,它仍然返回d
。
我期望在这种情况下它将返回空的then。它看起来像一只虫子。见http://www.pcreview.co.uk/forums/problem-getcharindexfromposition-t4037504.html
怎么会是bug?如果您查看描述,它会得到最接近的字符。最接近你点击的位置的字符实际上是最后一个字母。我没有看到源代码,但根据描述,它是按预期工作的。
在我对RichTextBox
可用的方法的简要查看中,我没有看到一个可以轻松解决问题的方法。你可以做的是用一个实际的字符填充文本的结尾,例如:一个空格。
//...
string originalText = richTextBox1.Text;
richTextBox1.Text += " ";
//Your code to get the index and substring
//Return the textbox to its original state
richTextBox1.Text = originalText;
richTextBox1.SelectionLength = 0;
richTextBox1.SelectionStart = positionBegin;
应该做你正在寻找的,但它是相当简单的,将是低效的取决于你正在处理的文本量。如果您想创建一个功能类似GetCharIndexFromPosition(Point pt)
的方法,您可能会在非托管代码领域结束。
编辑:因为我很好奇(扩展方法解决方案)
我开始查看RichTextBox
控件的源代码,它确实阻止你选择文本长度的最大长度以外的字符,如下所示:
public override int GetCharIndexFromPosition(Point pt) {
NativeMethods.POINT wpt = new NativeMethods.POINT(pt.X, pt.Y);
int index = (int)UnsafeNativeMethods.SendMessage(new HandleRef(this, Handle), NativeMethods.EM_CHARFROMPOS, 0, wpt);
string t = this.Text;
//This bit is stopping you from getting an index outside the length of the text
if (index >= t.Length) {
index = Math.Max(t.Length - 1, 0);
}
return index;
}
"fix"你可以创建一个扩展方法,以同样的方式实现它,但删除检查索引是否大于文本长度的部分:
public static class RichTextBoxExtensions
{
private const int EM_CHARFROMPOS = 0x00D7;
public static int GetTrueIndexPositionFromPoint(this RichTextBox rtb, Point pt)
{
POINT wpt = new POINT(pt.X, pt.Y);
int index = (int)SendMessage(new HandleRef(rtb, rtb.Handle), EM_CHARFROMPOS, 0, wpt);
return index;
}
[DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(HandleRef hWnd, int msg, int wParam, POINT lParam);
}
[StructLayout(LayoutKind.Sequential)]
internal class POINT
{
public int x;
public int y;
public POINT()
{
}
public POINT(int x, int y)
{
this.x = x;
this.y = y;
}
}
这样你就回到了原来的代码!只需将GetCharIndexFromPosition
更改为GetTrueIndexPositionFromPoint
,它将按预期工作
另一个(简单的)解决方案。
我也有同样的问题,只有在我的情况下,富文本框在自定义透明面板下面,在单击透明面板后,我必须将光标放在富文本框内的正确位置。这是我决定使用的一个解决方案,因为所有其他解决方案看起来都更复杂。只需获得富文本框中最后一个字符的点。然后将其与您单击的位置进行比较,并根据比较结果进行适当的调整。看看我在应用程序中使用的代码。注意'GetCharIndexFromPosition()'
和'GetPositionFromCharIndex()'
。我希望这能帮助下一个人,或者至少激发他们的创造力,想出一个更聪明的解决方案。
private void transparentPanel_Click(object sender, System.EventArgs e)
{
var mouseEventArgs = e as MouseEventArgs;
if (mouseEventArgs.Button == MouseButtons.Left)
{
// If currently in text editing mode
if (m_currentSelectedControl == e_SelectedControl.TEXT)
{
Point capturedPoint = new Point(mouseEventArgs.X, mouseEventArgs.Y);
int charIndex = richTextBox.GetCharIndexFromPosition(capturedPoint);
int lastChar = richTextBox.TextLength;
Point lastCharPoint = richTextBox.GetPositionFromCharIndex(lastChar);
if (lastCharPoint.X == capturedPoint.X ||
lastCharPoint.Y < capturedPoint.Y)
{
charIndex++;
}
richTextBox.SelectionStart = charIndex;
richTextBox.SelectionLength = 0;
richTextBox.Select();
transparentPanel.Refresh();
}
}
}
这是已知的记录行为。GetCharIndexFromPosition方法文档的备注部分包含以下重要说明:
如果指定的位置不在客户端矩形内控件,或者超出控件中的最后一个字符,返回Value是最后一个字符的索引。