Search code examples
c#wpfevent-handlingtooltipmouse

How to hide a tooltip when moving the mouse


I would like to adapt the behaviour of a System.Windows.Forms.ToolTip component: the content of the tooltip is quite large and instead of modifying the AutoDelay I would like to modify the behaviour of the tooltip: instead of being hidden after a fix amount of time, I would like it to be hidden when the user moves his or her mouse after the tooltip has been shown. I would like this to be done regardless of the position of the mouse (the mouse cursor might even not be present above the application at that moment).
In case this is possible, I would like to know if there is a way to get this done for all tooltips in a form.

What have I tried? Well, not much in fact: I have the tooltip and the corresponding text is present in the resources file:

private System.Windows.Forms.ToolTip toolTip1;
...
this.toolTip1.SetToolTip(this,
                         resources.GetString("$this.ToolTip"));

resx file:

    <data name="$this.ToolTip" xml:space="preserve">
      <value>There are two ways to use this application:
             ...

Just to be clear: I don't want any other behaviour of the tooltip: the location, the delay it takes for popping up, ..., everything is ok. I'm just interested in keeping it on screen until the mouse moves.


Solution

  • Yes it is possible. Override the OnMouseMove method to update a class variable of type Point (say: lastPoint), use the current e.Location to create and inflate a Rectangle, and if the rectangle does not contain the lastPoint, hide the tooltip.

    public partial class YourForm : Form
    {
        private Point lastPoint;
    
        public YourForm()
        {
            InitializeComponent();
        }
    
        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);
    
            if (lastPoint == Point.Empty)
                lastPoint = e.Location;
            else if (!new Rectangle(e.X - 16, e.Y - 16, 32, 32).Contains(lastPoint))
            {
                toolTip1.Hide(this);
                lastPoint = e.Location;
            }
        }    
    }
    

    A better approach is to subclass the ToolTip component to apply that for any control that supports the tooltip feature.

    [DesignerCategory("Code")]
    [ToolboxBitmap(typeof(ToolTip))]
    public class ToolTipEx : ToolTip
    {
        private Point lastPoint;
    
        public ToolTipEx() : base() { }
    
        public ToolTipEx(IContainer cont) : this() => cont.Add(this);
    
        /// <inheritdoc cref="ToolTip.SetToolTip(Control, string)"/>
        public new void SetToolTip(Control control, string caption)
        {
            base.SetToolTip(control, caption);
            control.MouseMove -= OnControlMouseMove;
            control.MouseMove += OnControlMouseMove;
        }
    
        private void OnControlMouseMove(object sender, MouseEventArgs e)
        {
            if (lastPoint == Point.Empty)
                lastPoint = e.Location;
            else if (!new Rectangle(e.X - 16, e.Y - 16, 32, 32).Contains(lastPoint))
            {
                Hide(sender as Control);
                lastPoint = e.Location;
            }
        }
    }
    

    You can set the tooltips at design-time using the designer as usual or at runtime by calling the .SetToolTip(..) method.

    SOQ69672832