鼠标悬停在文本上时显示工具提示

21

我想在自定义富文本控件中,当鼠标悬停在链接上时显示提示。考虑以下文本:

我们都在夜晚睡觉

在我的情况下,单词睡觉是一个链接。

当用户将鼠标移动到链接下方,即“睡觉”时,我想为该链接显示一个工具提示。

以下方法浮现在我的脑海中,但它们并没有起作用:

1)捕获 OnMouseHover 事件

if(this.Cursor == Cursors.Hand)
   tooltip.Show(textbox,"My tooltip");
else
   tooltip.Hide(textbox);

但是这个方法行不通。

更新

提到的链接不是URL,也就是说这些是自定义链接,因此正则表达式在这里帮助不大,它可以是任何文本。用户可以选择将其创建为链接。

虽然我还没有尝试GetPosition方法,但我认为它在设计和维护方面不太优雅。

假设我有以下行,在我的richedit框中

我们晚上睡觉。但蝙蝠却保持清醒。蟑螂在晚上变得活跃

在上面的句子中,当鼠标悬停在它们上面时,我想要三个不同的工具提示。

sleep -> Human beings
awake -> Nightwatchman here
active -> My day begins

我使用以下代码来捕获 OnMouseMove 事件:

与消息框交互

OnMouseMove( )
{

   // check to see if the cursor is over a link
   // though this is not the correct approach, I am worried why does not a tooltip show up
   if(this.Cursor.current == Cursors.hand )
   {
     Messagebox.show("you are under a link");
   }
}

无法工作 - 包含提示 - 提示未显示

OnMouseMove( MouseventArgs e )
{

   if(cursor.current == cursors.hand )
   {
     tooltip.show(richeditbox,e.x,e.y,1000);
   }
}

这就是诀窍... tooltip.Active = true - Sujay Ghosh
1
哦,我没意识到你的问题是关于工具提示本身的... 无论如何,使用 System.Windows.Forms.Cursor.Current 静态获取当前鼠标指针,就像我的上一个回答中提到的一样。 - Shimmy Weitzhandler
9个回答

23

只需从工具箱中添加ToolTip工具到窗体中,并在您想要使工具提示在其MouseMove事件上启动的任何控件的MouseMove事件中添加此代码即可。

private void textBox3_MouseMove(object sender, MouseEventArgs e)
    {
      toolTip1.SetToolTip(textBox3,"Tooltip text"); // you can change the first parameter (textbox3) on any control you wanna focus
    }

希望它能帮助到你

祝福平安


2
只需要在第一次设置toolTip1.SetToolTip(textBox3,"Tooltip text");,而不是每次鼠标移动事件被触发时都设置。 - anion

16

看一下,这个可以运行。如果您有问题,请告诉我:

using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1() { InitializeComponent(); }

        ToolTip tip = new ToolTip();
        void richTextBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (!timer1.Enabled)
            {
                string link = GetWord(richTextBox1.Text, richTextBox1.GetCharIndexFromPosition(e.Location));
                //Checks whether the current word i a URL, change the regex to whatever you want, I found it on www.regexlib.com.
//you could also check if current word is bold, underlined etc. but I didn't dig into it.
                if (System.Text.RegularExpressions.Regex.IsMatch(link, @"^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~])*$"))
                {
                    tip.ToolTipTitle = link;
                    Point p = richTextBox1.Location;
                    tip.Show(link, this, p.X + e.X,
                        p.Y + e.Y + 32, //You can change it (the 35) to the tooltip's height - controls the tooltips position.
                        1000);
                    timer1.Enabled = true;
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e) //The timer is to control the tooltip, it shouldn't redraw on each mouse move.
        {
            timer1.Enabled = false;
        }

        public static string GetWord(string input, int position) //Extracts the whole word the mouse is currently focused on.
        {
            char s = input[position];
            int sp1 = 0, sp2 = input.Length;
            for (int i = position; i > 0; i--)
            {
                char ch = input[i];
                if (ch == ' ' || ch == '\n')
                {
                    sp1 = i;
                    break;
                }
            }

            for (int i = position; i < input.Length; i++)
            {
                char ch = input[i];
                if (ch == ' ' || ch == '\n')
                {
                    sp2 = i;
                    break;
                }
            }

            return input.Substring(sp1, sp2 - sp1).Replace("\n", "");
        }
    }
}

5

您不应该使用私有提示控件,而应该使用表单提示控件。以下示例可以正常工作:

public partial class Form1 : Form
{
    private System.Windows.Forms.ToolTip toolTip1;

    public Form1()
    {
        InitializeComponent();
        this.components = new System.ComponentModel.Container();
        this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);

        MyRitchTextBox myRTB = new MyRitchTextBox();
        this.Controls.Add(myRTB);

        myRTB.Location = new Point(10, 10);
        myRTB.MouseEnter += new EventHandler(myRTB_MouseEnter);
        myRTB.MouseLeave += new EventHandler(myRTB_MouseLeave);
    }


    void myRTB_MouseEnter(object sender, EventArgs e)
    {
        MyRitchTextBox rtb = (sender as MyRitchTextBox);
        if (rtb != null)
        {
            this.toolTip1.Show("Hello!!!", rtb);
        }
    }

    void myRTB_MouseLeave(object sender, EventArgs e)
    {
        MyRitchTextBox rtb = (sender as MyRitchTextBox);
        if (rtb != null)
        {
            this.toolTip1.Hide(rtb);
        }
    }


    public class MyRitchTextBox : RichTextBox
    {
    }

}

2
这并不是一种优雅的方法,但您可以使用RichTextBox.GetCharIndexFromPosition方法返回鼠标当前所在字符的索引,然后使用该索引来确定它是否位于链接、热点或任何其他特殊区域上。如果是的话,显示您的工具提示(您可能需要将鼠标坐标传递到工具提示的Show方法中,而不仅仅是传递文本框,以便工具提示可以放置在链接旁边)。

示例在这里:http://msdn.microsoft.com/en-us/library/system.windows.forms.richtextbox.getcharindexfromposition(VS.80).aspx


我只是为了测试在richedit框的MouseMove事件中做了以下操作:if(Cursor.Current == Cursors.Hand) Messagebox.Show("My Tooltip);但是当我用下面的tooltip.show()替换Messagebox时,我的提示框没有显示出来:if(Cursor.Current == Cursors.Hand) this.ttpLink.Show("Hover",txtBox,e.X,e.Y,1000);我错过了什么吗? - Sujay Ghosh
Jean,即使我得到了文本,我怎么知道字符串是链接? - Sujay Ghosh

0
如果您正在使用RichTextBox控件,您可以简单地定义ToolTip对象,并在鼠标在RichTextBox控件内移动并选择文本时显示工具提示。
    ToolTip m_ttInput = new ToolTip(); // define as member variable

    private void rtbInput_SelectionChanged(object sender, EventArgs e)
    {
        if (rtbInput.SelectedText.Length > 0) 
        {
            m_ttInput.Show(rtbInput.SelectedText.Length.ToString(), rtbInput, 1000);
        }
    }

0

使用:

ToolTip tip = new ToolTip();
private void richTextBox1_MouseMove(object sender, MouseEventArgs e)
{
    Cursor a = System.Windows.Forms.Cursor.Current;
    if (a == Cursors.Hand)
    {
        Point p = richTextBox1.Location;
        tip.Show(
            GetWord(richTextBox1.Text,
                richTextBox1.GetCharIndexFromPosition(e.Location)),
            this,
            p.X + e.X,
            p.Y + e.Y + 32,
            1000);
    }
}

使用我之前回答中的GetWord函数获取悬停单词。 使用计时器逻辑禁用重新显示工具提示,就像上一个示例中一样。
在上面的示例中,工具提示通过检查鼠标指针来显示悬停单词。
如果这个答案仍然不是你想要的,请说明表征你想要使用工具提示的单词的条件。 如果你想要为加粗的单词使用它,请告诉我。

0
我还想在这里补充一点,如果在程序运行之前加载包含工具提示控件的所需表单,则该表单上的工具提示控件将无法按照下面所述正常工作...
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        objfrmmain = new Frm_Main();
        Showtop();//this is procedure in program.cs to load an other form, so if that contain's tool tip control then it will not work
        Application.Run(objfrmmain);


    }

所以我通过将以下代码放入Fram_main_load事件过程中来解决这个问题,就像这样

    private void Frm_Main_Load(object sender, EventArgs e)
    {
        Program.Showtop();
    }

0
为了方便使用和易于理解。
您可以在表单上的任何位置(从工具箱中)简单地放置一个工具提示。然后,您将在表单中的其他所有内容的属性中获得选项,以确定在该工具提示中显示什么(它会读取类似“toolTip1上的ToolTip”这样的内容)。每当您悬停在对象上时,该属性中的文本将显示为工具提示。
不包括像原始问题所要求的自定义即时工具提示。但我将其留在这里供其他不需要的人使用。

-1

由于这个问题(除了它的年龄)并不需要在Windows.Forms中解决,因此以下是一种在WPF中使用代码后台完成此操作的方法。

TextBlock tb = new TextBlock();
tb.Inlines.Add(new Run("Background indicates packet repeat status:"));
tb.Inlines.Add(new LineBreak());
tb.Inlines.Add(new LineBreak());
Run r = new Run("White");
r.Background = Brushes.White;
r.ToolTip = "This word has a White background";
tb.Inlines.Add(r);
tb.Inlines.Add(new Run("\t= Identical Packet received at this time."));
tb.Inlines.Add(new LineBreak());
r = new Run("SkyBlue");
r.ToolTip = "This word has a SkyBlue background";
r.Background = new SolidColorBrush(Colors.SkyBlue);
tb.Inlines.Add(r);
tb.Inlines.Add(new Run("\t= Original Packet received at this time."));

myControl.Content = tb;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接