Why can’t I display a tooltip for a disabled window?


Here's a question that floated past my field of view some time ago:

When the mouse hovers over a disabled window, the tooltip associated with that window does not appear. Why is this? Why isn't this documented in MSDN?

Actually, you already know the answer, and it is documented. You just have to connect the dots.

When a window is disabled, it does not receive keyboard or mouse input. The documentation for EnableWindow says so in so many words, right in the first sentence.

Next, how do tooltips know when to appear and disappear? Well, one way is to modify your window procedure so it takes all its input messages and forwards them to the tooltip control via the TTM_RELAYEVENT message. That way, the tooltip control knows where the mouse is and can show and hide itself accordingly. Alternatively, you can use the TTF_SUBCLASS flag to tell the tooltip control to subclass the tool window and grab the input itself. Both of these methods are also documented.

Now put this all together. The tooltip control peeks at all the input destined for the tool window, either automatically via TTF_SUBCLASS or manually with TTM_RELAYEVENT. If the window is disabled, then it receives no input. Consequently, the tooltip control has no input to peek at and therefore doesn't know when to appear or disappear.

This is also why you don't get tooltips for hidden windows and why you don't get tooltips when the mouse is captured to another window.

So you see, you knew the answer all along. You just didn't realize it.

Comments (16)
  1. Sunil says:

    When the mouse hovers over a disabled button in IE, the tooltip does show.

    What magic is happening here?

    Is the button not really disabled?

    [It’s not a button. I discussed this over two years ago. –Raymond]
  2. Jack Mathews says:

    I love posts like this one.  The "connect the dots" posts of seemingly disparate parts of Win32.

  3. Daniel Garlans says:

    I love posts like this one, specifically because it’s one of those things that are so obvious that you tend to overlook it. I’d say this is an extremely good example of learning to read and understand, and learning how to extrapolate, the consequences of API actions.

    So, I for one say, Raymond, keep this kind of thing coming!

  4. JamesNT says:

    Paraphrasing the great master, Raymond Chen:

    "I can’t believe he had to explain that."

    JamesNT

  5. codekaizen says:

    You can, however, do this in WPF:

    Button b = new Button();

    ToolTipService.SetShowOnDisabled(b, true);

    Kudos to the WPF team. I’m still fathoming how profoundly they’ve succeeded with their design. Little realizations like this one keep delighting me.

  6. Cooney says:

    A related weirdness I’ve found: I run cygwin/X, and it will pop up emacs tooltips (not the windows flavor) when the window is under another one. Probably just bad code somewhere that I could fix in my CFT…

  7. I’m curious about the API choice of having one function, EnableWindow(bool), compared to having two functions, EnableWindow and DisableWindow.

  8. Adam Glasgall says:

    That’s not just an Emacs/X11 thing, Cooney. It happens on my Mac with Carbon Emacs too. I’ve wondered about that for a while.

  9. Chris Hanson says:

    Toolbar buttons also aren’t actually Windows. The Toolbar is a Window, but the buttons within it are just drawn individually without having actual Windowhood.

  10. Igor says:

    As long as your parent control knows where the mouse is, it can fire tooltips at will, right?

  11. Dan McCarty says:

    Presumably this doesn’t apply to *toolbar* button s…?  Is there a reasoning behind that difference?  Or is it just a function of disabled windows not receiving mouse input, whereas toolbar frames (e.g., ToolbarWindow32) do?

  12. PatriotB says:

    @codekaizen — I personally haven’t done much exploring of WPF yet, but I agree with you.  Ah, the things you can accomplish with 6 years of development time, and 20 years of Win32’s history (pluses/minuses, lessons learned) to learn from. :)

  13. Jonathan says:

    David Phillips: I think it eases development of wrappers:

    void EnableAllWindows (bool b)

    {

     EnableWindows(hWnd1, b);

     EnableWindows(hWnd2, b);

     …

    }

    The name is misleading though – maybe it should’ve been called "SetWindowEnablement"?

  14. Harold Hunt says:

    Cooney and Adam – I’m one of the original authors of Cygwin/X.  The tooltips popping up from an obscured window is due to a deficiency in our window manager continuing to route mouse messages to windows that should not be receiving them.  The tooltips are not rendering using the same mechanism that Raymond describes for Win32, instead, they are rendered by whatever mechanism each particular X11 app uses to render them.  Thus, some applications will show tooltips when they are obscured and others will not, it all depends on the mechanism or toolkit that the app is using.

    This problem happens on X11 for Mac OS X as well since we both handle our input the same way… it’s sort of random but we both have the same "bug" because it was the easiest way to solve the problem and it got us 99% of the way there :)

    When I worked for StarNet (maker’s of X-Win32), we used a lot of the code that we’d written for Cygwin/X so we had this same bug for a little while, but we later fixed it since we had the time to do so.

    Hope that helps,

    Harold

  15. Dmitry Vasilevsky says:

    http://msdn2.microsoft.com/en-us/library/system.windows.forms.tooltip(VS.71).aspx

    Note   ToolTip text is not displayed for controls that are disabled.

    Looking from "inside" of Win32 I understand the reasoning. However, as an application developer I think it’s just wrong. I hate when UI controls are grayed out and I don’t know the reason why. Every disabled control MUST tell why it is disabled. And one of the good ways to do so is to display this reason in the tooltip. It is out of the way if you are not interested. And it pops up if you trying to figure it out. No, you can’t do that. You have to invent your own code to hack around it.

  16. Miral says:

    If you *really* want to do that, then make a little annotation control (like the ErrorProvider in .NET) that attaches itself to a disabled control and can tell the user why it’s disabled.

    Usually, though, windows are disabled for very obvious reasons — if you find the need to explain why something is disabled then possibly your UI design needs improvement.

Comments are closed.

Skip to main content