3


0

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(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;
    }
}

これは、 `#`で始まる単語を検出し、マウスカーソルがそれらの上にあるときにマウスカーソルを手にします。 ただし、次の2つの問題があります。

  1. `richTextBox1`のダブルクリックイベントを実装しようとすると、 単語がクリックされたときにそれを検出しますが、その単語は強調表示(選択)されます。これは避けたいと思います。 テキストの末尾を選択することでプログラムで選択を解除できますが、ちらつきが発生するため、これを回避したいと思います。 これを行うにはどのような方法がありますか?

  2. `GetCharIndexFromPosition`メソッドは、 カーソルに最も近い文字。 つまり、RichTextBoxに含まれているのが `#`で始まる単語だけである場合、リッチテキストコントロールのどこにいてもカーソルは手になります。 興味のある単語の一部である実際の単語または文字の上にカーソルを置いたときに手だけになるようにするにはどうすればよいですか? 実装されたURL検出にもこの問題が部分的にあります。 URLの検出を有効にし、リッチテキストエディターで「www.test.com」のみを書き込むと、カーソルはリンク上(またはその下)にある限り手になります。 ただし、リンクの右側にある場合は手になりません。 カーソルを手にすると、テキスト上にあるのが難しすぎる場合にのみ、この機能を使用しても問題ありません。

何らかの種類のWindows API呼び出しに頼らなければならないだろうと思うが、どこから始めればよいかわからない。

Visual Studio 2008を使用していますが、これを自分で実装したいと思います。

*更新:*ちらつきの問題は、ダブルクリックでテキストを選択できず、マウスカーソルをドラッグしてプログラムで選択できるようにすれば解決します。 これを達成するのは簡単ですか? この場合、ダブルクリックでテキストを選択できるかどうかはあまり気にしません。

1 Answer


2


ポイント(2)で試すことができます:

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を使用すると、単語が選択されるという問題を回避できる可能性があります…​