我想在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
。
我希望在这种情况下它会返回空。它看起来像一个bug。见http://www.pcreview.co.uk/forums/problem-getcharindexfromposition-t4037504.html
答案 0 :(得分:4)
这怎么一个错误?如果您查看描述,它会获得最接近的字符。与您单击的位置最接近的字符确实是最后一个字母。我没有看到来源,但根据描述,它正在按预期工作。
在我简要介绍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;
}
要“修复”这个,您可以创建一个以相同方式实现它的扩展方法,但删除有关检查索引是否大于文本长度的位:
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
即可按预期工作。
答案 1 :(得分:0)
另一个(简单)解决方案。
我有同样的问题,只有在我的情况下,富文本框位于自定义透明面板下方,点击透明面板时我必须将光标放在右侧富文本框中的位置。这是我决定使用的解决方案,因为所有其他解决方案看起来更复杂。只需获取富文本框中最后一个字符的点即可。然后将其与您点击的位置进行比较,并根据比较结果进行适当的调整。看看我用于我的应用程序的代码。请注意'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();
}
}
}
答案 2 :(得分:0)
这是一种已知的记录行为。 GetCharIndexFromPosition方法文档的“备注”部分包含以下重要说明:
如果指定的位置不在客户端矩形内 控制,或超出控件中的最后一个字符,返回 value是最后一个字符的索引。