确定鼠标悬停在快速着色文本框中的单词上

本文关键字:文本 单词 鼠标 悬停 | 更新日期: 2023-09-27 18:36:04

我正在使用FastColoredTextBox项目,无法弄清楚如何确定触发鼠标悬停事件时鼠标悬停在哪个单词(或字符位置)(因此我可以显示有关单词用法的提示)。我发现了一个类似的SO问题,尽管它只涉及一个方便具有GetCharIndexFromPosition方法的RichTextBox

这可能是一个很长的机会,但这里有人以这种方式与FastColoredTextBox合作并可以提供帮助吗?

否则,在源中窥探FastColoredTextBox我实际上无法告诉它用于绘制文本的控件。虽然我从它的类声明中怀疑

public partial class FastColoredTextBox : UserControl, ISupportInitialize

它可能会自己做。我认为我最好的选择是看看RickTextBox如何实现GetCharIndexFromPosition并尝试用FastColoredTextBox重新创建它。

关于如何处理这个问题的任何建议?

编辑:在FCTB的源代码中,我从MouseClick事件开始,因为当用户单击文本时,此事件会移动光标,因此它必须在鼠标下方的某个点从字符开始。在事件处理程序中,我找到了方法public Place PointToPlace(Point point) 。看起来这可能是我正在寻找的。

如果这能让我找到解决方案,我将发布问题的答案。

确定鼠标悬停在快速着色文本框中的单词上

PointToPlace返回一个Place,告诉您行和字符索引(在行上)。
PointToPosition返回绝对字符位置。
我对此进行了测试(在 vb.net...),它没有优化,而是第一次启动并且到目前为止可以工作:

Private Sub test_MouseMove(snd As Object, e As MouseEventArgs)
    Dim p As Integer = Me.fctb.PointToPosition(Me.fctb.PointToClient(Windows.Forms.Cursor.Position))
    ' display letter
    Dim ch As String = ""
    If p < Me.fctb.Text.Length Then ch = Me.fctb.Text.ToCharArray()(p)
    Me.Label1.Text = ch
    ' display word
    Me.Label2.Text = GetWord(Me.fctb, p)
End Sub
Private Function GetWord(ct As FastColoredTextBoxNS.FastColoredTextBox, p As Integer) As String
    Dim sb As New StringBuilder(ct.Text)
    If sb.Length = 0 OrElse p = sb.Length Then Return ""
    If Not Regex.IsMatch(sb.Chars(p).ToString, "^'w$") Then Return sb.Chars(p).ToString
    Dim n1 As Integer = p
    While n1 > 0 AndAlso Regex.IsMatch(sb.Chars(n1 - 1).ToString, "^'w$")
        n1 -= 1
    End While
    Dim n2 As Integer = p
    While n2 < sb.Length AndAlso Regex.IsMatch(sb.Chars(n2 + 1).ToString, "^'w$")
        n2 += 1
    End While
    Return sb.ToString.Substring(n1, n2 - n1 + 1)
End Function

C# 代码:

private void test_MouseMove(object snd, MouseEventArgs e) {
    var p = fctb.PointToPosition(fctb.PointToClient(Windows.Forms.Cursor.Position));
    // display letter
    var ch = "";
    if (p < fctb.Text.Length) {
        ch = fctb.Text[p].ToString();
    }
    Label1.Text = ch;
    // display word
    Label2.Text = GetWord(fctb, p);
}
private string GetWord(FastColoredTextBoxNS.FastColoredTextBox ct, int p) {
    var sb = new StringBuilder(ct.Text);
    if (sb.Length == 0 || p == sb.Length) return "";
    if (!Regex.IsMatch(sb[p].ToString(), @"^'w$")) return sb[p].ToString();
    var n1 = p;
    while (n1 > 0 && Regex.IsMatch(sb[n1 - 1].ToString(), @"^'w$")) {
        n1 -= 1;
    }
    var n2 = p;
    while (n2 < sb.Length && Regex.IsMatch(sb[n2 + 1].ToString(), @"^'w$")) {
        n2 += 1;
    }
    return sb.ToString().Substring(n1, n2 - n1 + 1);
}

好吧,我已经决定MouseHover事件不是我希望显示有关单词的信息的方式。当我想要时它不会触发,我想我将使用键盘快捷键来显示我想要的信息。

虽然在我

退出之前,我确实在 C# 中提出了这个部分解决方案。它有一些错误。当将鼠标悬停在文本的最后一个单词上时,有时会出现问题。此外,我觉得我将charString混合在一起会导致一些我没有追踪到的深奥问题。

private void fctbEditor_MouseHover(object sender, EventArgs e)
{
    int charIndex = fctbEditor.PointToPosition(fctbEditor.PointToClient(Cursor.Position));
    if (charIndex != fctbEditor.Text.Length && fctbEditor.Text.Length > 0 && fctbEditor.Text[charIndex] != ' ')
    {
        String hoverWord = GetWord(charIndex);
        // Do with the word as you please
        Console.Out.WriteLine(" - Index: " + charIndex + " Char[" + fctbEditor.Text[charIndex].ToString() + "] Word[" + hoverWord + "]");
    }
}
private String GetWord(int charPos)
{
    int revPos = charPos;
    char curChar = fctbEditor.Text[revPos];
    while (curChar != ' ' && curChar != ''n' && revPos > 0)
    {
        revPos -= 1;
        curChar = fctbEditor.Text[revPos];
    }
    int forPos = charPos;
    curChar = fctbEditor.Text[forPos];
    while(curChar != ' ' && curChar != ''n' && forPos < fctbEditor.Text.Length)
    {
        forPos += 1;
        curChar = fctbEditor.Text[forPos];
    }
    return fctbEditor.Text.Substring(revPos + 1, forPos - revPos - 1);
}