RichTextBox中的自定义链接

假设我希望以#开头的每个单词都能在双击时生成一个事件。 为此,我实现了以下测试代码:

 private bool IsChannel(Point position, out int start, out int end) { if (richTextBox1.Text.Length == 0) { start = end = -1; return false; } int index = richTextBox1.GetCharIndexFromPosition(position); int stop = index; while (index >= 0 && richTextBox1.Text[index] != '#') { if (richTextBox1.Text[index] == ' ') { break; } --index; } if (index < 0 || richTextBox1.Text[index] != '#') { start = end = -1; return false; } while (stop < richTextBox1.Text.Length && richTextBox1.Text[stop] != ' ') { ++stop; } --stop; start = index; end = stop; return true; } private void richTextBox1_MouseMove(object sender, MouseEventArgs e) { textBox1.Text = richTextBox1.GetCharIndexFromPosition(new Point(eX, eY)).ToString(); int d1, d2; if (IsChannel(new Point(eX, eY), out d1, out d2) == true) { if (richTextBox1.Cursor != Cursors.Hand) { richTextBox1.Cursor = Cursors.Hand; } } else { richTextBox1.Cursor = Cursors.Arrow; } } 

它处理检测以#开头的单词,并在鼠标hover在它们上方时使鼠标指针成为一只手。 但是,我有以下两个问题:

  1. 如果我尝试为richTextBox1实现双击事件,我可以检测单击一个单词的时间,但是该单词被突出显示(选中),我想避免。 我可以通过选择文本的结尾以编程方式取消选择它,但这会导致闪烁,我想避免。 有什么方法可以做到这一点?
  2. GetCharIndexFromPosition方法返回最接近游标的字符的索引。 这意味着,如果我的RichTextBox包含的唯一内容是以#开头的单词,则无论富文本控件位于何处,光标都将成为一只手。 我怎样才能让它只是一只手,当它hover在我感兴趣的单词的实际单词或字符上时? 实施的URL检测也部分地受到这个问题的困扰。 如果我启用URL检测并且只在富文本编辑器中编写www.test.com ,只要它在链接上或下面 ,光标就会成为一只手。 但是,如果它位于链接的右侧,则不会是一只手。 即使使用此function我也很好,如果将光标放在手上,并且只有在文本上certificate它太难。

我猜我不得不求助于某种Windows API调用,但我真的不知道从哪里开始。

我正在使用Visual Studio 2008,我想自己实现。

更新:如果我可以通过双击,只有通过拖动鼠标光标并以编程方式选择文本,就可以解决闪烁问题。 这更容易实现吗? 因为我真的不在乎是否可以通过双击来选择文本。

在第(2)点你可以尝试:

if (richTextBox1.Text.Length == 0){ ... }之后if (richTextBox1.Text.Length == 0){ ... }

 //get the mouse point in client coordinates Point clientPoint = richTextBox1.PointToClient(richTextBox1.PointToScreen(position)); int index = richTextBox1.GetCharIndexFromPosition(position); //get the position of the closest char Point charPoint = richTextBox1.GetPositionFromCharIndex(index); bool notOnTheSameLine = ((clientPoint.Y < charPoint.Y) || (clientPoint.Y > charPoint.Y + richTextBox1.Font.Height)); bool passedTheWord = (clientPoint.X > charPoint.X + richTextBox1.Font.SizeInPoints); if (notOnTheSameLine || passedTheWord) { start = end = -1; return false; }
//get the mouse point in client coordinates Point clientPoint = richTextBox1.PointToClient(richTextBox1.PointToScreen(position)); int index = richTextBox1.GetCharIndexFromPosition(position); //get the position of the closest char Point charPoint = richTextBox1.GetPositionFromCharIndex(index); bool notOnTheSameLine = ((clientPoint.Y < charPoint.Y) || (clientPoint.Y > charPoint.Y + richTextBox1.Font.Height)); bool passedTheWord = (clientPoint.X > charPoint.X + richTextBox1.Font.SizeInPoints); if (notOnTheSameLine || passedTheWord) { start = end = -1; return false; } 

对于点(1),可能有一种不同的方式来跟踪链接而不是dbl-click? 也许cntl-click会避免单词被选中的问题……