RichTextBox 中的自定义链接

Custom links in RichTextBox(RichTextBox 中的自定义链接)
本文介绍了RichTextBox 中的自定义链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I want every word starting with a # to generate an event on double click. For this I have implemented the following test code:

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(e.X, e.Y)).ToString();
    int d1, d2;
    if (IsChannel(new Point(e.X, e.Y), out d1, out d2) == true)
    {
        if (richTextBox1.Cursor != Cursors.Hand)
        {
            richTextBox1.Cursor = Cursors.Hand;
        }
    }
    else
    {
        richTextBox1.Cursor = Cursors.Arrow;
    }
}

这处理检测以 # 开头的单词,并在鼠标悬停在它们上方时使鼠标光标成为手.但是,我有以下两个问题:

This handles detecting words that start with # and making the mouse cursor a hand when it hovers over them. However, I have the following two problems:

  1. 如果我尝试为 richTextBox1 实现双击事件,我可以检测到单击某个单词的时间,但是该单词被突出显示(选中),我想避免这种情况.我可以通过选择文本的结尾以编程方式取消选择它,但这会导致闪烁,我想避免这种情况.有什么方法可以做到这一点?
  2. GetCharIndexFromPosition 方法返回离光标最近的字符的索引.这意味着如果我的 RichTextBox 包含的唯一内容是以 # 开头的单词,那么无论富文本控件位于何处,光标都将是一只手.当它悬停在我感兴趣的单词的一部分的实际单词或字符上时,我怎样才能使它成为一只手?实现的 URL 检测也部分地受到这个问题的影响.如果我启用 URL 检测并且只在富文本编辑器中编写 www.test.com,则光标只要在 或以下 链接上就会是一只手.但是,如果它位于链接的右侧,它将不是一只手.如果使光标成为手,当且仅当它在文本上被证明太难时,即使使用此功能我也很好.
  1. If I try to implement a double click event for richTextBox1, I can detect when a word is clicked, however that word is highlighted (selected), which I'd like to avoid. I can deselect it programmatically by selecting the end of the text, but that causes a flicker, which I would like to avoid. What ways are there to do this?
  2. The GetCharIndexFromPosition method returns the index of the character that is closest to the cursor. This means that if the only thing my RichTextBox contains is a word starting with a # then the cursor will be a hand no matter where on the rich text control it is. How can I make it so that it is only a hand when it hovers over an actual word or character that is part of a word I'm interested in? The implemented URL detection also partially suffers from this problem. If I enable detection of URLs and only write www.test.com in the rich text editor, the cursor will be a hand as long as it is on or below the link. It will not be a hand if it's to the right of the link however. I'm fine even with this functionality if making the cursor a hand if and only if it's on the text proves to be too difficult.

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

I'm guessing I'll have to resort to some sort of Windows API calls, but I don't really know where to start.

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

I am using Visual Studio 2008 and I would like to implement this myself.

更新:如果我能做到,只有通过拖动鼠标光标并以编程方式才能通过双击来选择任何文本,那么闪烁问题将得到解决.这更容易实现吗?因为在这种情况下,我真的不在乎是否可以通过双击来选择文本.

Update: The flickering problem would be solved if I could make it so that no text is selectable through double clicking, only through dragging the mouse cursor and programmatically. Is this easier to achieve? Because I don't really care if one can select text or not by double clicking in this case.

推荐答案

关于第(2)点你可以试试:

On point (2) you could try:

之后 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;
}

<小时>

对于第 (1) 点,跟随链接的方式可能与 dbl-click 不同?也许 cntl-click 会避免单词被选中的问题......


For point (1) maybe have a different way of following the link than dbl-click? Maybe cntl-click would avoid the issues of the word becoming selected...

这篇关于RichTextBox 中的自定义链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

DispatcherQueue null when trying to update Ui property in ViewModel(尝试更新ViewModel中的Ui属性时DispatcherQueue为空)
Drawing over all windows on multiple monitors(在多个监视器上绘制所有窗口)
Programmatically show the desktop(以编程方式显示桌面)
c# Generic Setlt;Tgt; implementation to access objects by type(按类型访问对象的C#泛型集实现)
InvalidOperationException When using Context Injection in ASP.Net Core(在ASP.NET核心中使用上下文注入时发生InvalidOperationException)
LINQ many-to-many relationship, how to write a correct WHERE clause?(LINQ多对多关系,如何写一个正确的WHERE子句?)