确定鼠标悬停在快速着色文本框中的单词上
本文关键字:文本 单词 鼠标 悬停 | 更新日期: 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# 中提出了这个部分解决方案。它有一些错误。当将鼠标悬停在文本的最后一个单词上时,有时会出现问题。此外,我觉得我将char
和String
混合在一起会导致一些我没有追踪到的深奥问题。
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);
}