Sam Mackrill
Sam Mackrill

Reputation: 4061

How can I show a tooltip on a disabled button?

If you have a disabled button on a winform how can you show a tool-tip on mouse-over to inform the user why the button is disabled?

Upvotes: 39

Views: 24232

Answers (5)

wjktrs
wjktrs

Reputation: 160

I had many GroupBox controls on my form, each of which contained numerous controls. The code below is what I had to use to get the tooltip to show directly over disabled TextBox controls.

In Form1_Load event use:

AddHandler GroupBox1.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox2.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox3.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox4.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox5.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox6.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox7.MouseMove, AddressOf GroupBoxMouseMove
AddHandler GroupBox8.MouseMove, AddressOf GroupBoxMouseMove

The stand alone method is:

Private Sub GroupBoxMouseMove(ByVal sender As Object, ByVal e As EventArgs)
    Dim parent = TryCast(sender, Control)
    If parent Is Nothing Then
        Return
    End If
    Dim pt As New System.Drawing.Point
    pt.X = MousePosition.X - sender.left
    pt.Y = MousePosition.Y - sender.top - 22
    TextBox18.Text = pt.X
    TextBox20.Text = pt.Y
    Dim ctrl = parent.GetChildAtPoint(pt)
    If ctrl IsNot Nothing AndAlso ctrl.Enabled = False Then
        If ctrl.Visible AndAlso ToolTip1.Tag Is Nothing Then
            Dim tipstring = ToolTip1.GetToolTip(ctrl)
            ToolTip1.Show("Show this text over disabled textbox.", ctrl, ctrl.Width \ 2, ctrl.Height \ 2)
            ToolTip1.Tag = ctrl
        End If
    Else
        ctrl = TryCast(ToolTip1.Tag, Control)
        If ctrl IsNot Nothing Then
            ToolTip1.Hide(ctrl)
            ToolTip1.Tag = Nothing
        End If
    End If

End Sub

Upvotes: 1

BobbyShaftoe
BobbyShaftoe

Reputation: 28499

So assuming your control is called button1 you could do something like this.
You have to do it by handling the MouseMove event of your form since the events won't be fired from your control.

bool IsShown = false;      

void Form1_MouseMove(object sender, MouseEventArgs e)
{
   Control ctrl = this.GetChildAtPoint(e.Location);

   if (ctrl != null)
   {
       if (ctrl == this.button1 && !IsShown)
       {
           string tipstring = this.toolTip1.GetToolTip(this.button1);                 
           this.toolTip1.Show(tipstring, this.button1, this.button1.Width /2, 
                                                       this.button1.Height / 2);
           IsShown = true;
       }
   }
   else
   {
       this.toolTip1.Hide(this.button1);
       IsShown = false;
   }

}

Upvotes: 8

Sam Mackrill
Sam Mackrill

Reputation: 4061

I have since adapted BobbyShaftoe's answer to be a bit more general

Notes:

  • The MouseMove event must be set on the parent control (a panel in my case)

    private void TimeWorks_MouseMove(object sender, MouseEventArgs e)
    {
        var parent = sender as Control;
        if (parent==null)
        {
            return;
        }
        var ctrl = parent.GetChildAtPoint(e.Location);
        if (ctrl != null && !ctrl.Enabled)
        {
            if (ctrl.Visible && toolTip1.Tag==null)
            {
                var tipstring = toolTip1.GetToolTip(ctrl);
                toolTip1.Show(tipstring, ctrl, ctrl.Width / 2, ctrl.Height / 2);
                toolTip1.Tag = ctrl;
            }
        }
        else
        {
            ctrl = toolTip1.Tag as Control;
            if (ctrl != null)
            {
                toolTip1.Hide(ctrl);
                toolTip1.Tag = null;
            }
        }
    
    }
    

Upvotes: 12

galaxis
galaxis

Reputation: 945

Place the button (or any control that fits this scenario) in a container (panel, tableLayoutPanel), and associate the tooltip to the appropriate underlying panel cell. Works great in a number of scenarios, flexible. Tip: make the cell just large enough to hold the bttn, so mouseover response (tooltip display) doesn't appear to "bleed" outside the bttn borders.

Upvotes: 15

Peter Smartt
Peter Smartt

Reputation: 358

Sam Mackrill, thanks for your answer, great idea to use the Tag to know what Control you are leaving. However you still need the IsShown flag as per BobbyShaftoe's answer. If you have the mouse in the wrong spot, if the ToolTip comes up under it, it can fire another MouseMove event (even though you did not physically move the mouse). This can cause some unwanted animation, as the tooltip continually disappears and reappears.

Here is my code:

    private bool toolTipShown = false;
    private void TimeWorks_MouseMove(object sender, MouseEventArgs e)
    {
        var parent = sender as Control;
        if (parent == null)
        {
            return;
        }
        var ctrl = parent.GetChildAtPoint(e.Location);
        if (ctrl != null)
        {
            if (ctrl.Visible && toolTip1.Tag == null)
            {
                if (!toolTipShown)
                {
                    var tipstring = toolTip1.GetToolTip(ctrl);
                    toolTip1.Show(tipstring.Trim(), ctrl, ctrl.Width / 2, ctrl.Height / 2);
                    toolTip1.Tag = ctrl;
                    toolTipShown = true;
                }
            }
        }
        else
        {
            ctrl = toolTip1.Tag as Control;
            if (ctrl != null)
            {
                toolTip1.Hide(ctrl);
                toolTip1.Tag = null;
                toolTipShown = false;
            }
        }
    }

Upvotes: 11

Related Questions