[Webinar] Streamline your web hosting managementRegister Today

  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1416
  • Last Modified:

Tooltips: tracking and working for disabled controls - how?

Ah hello.

I have a very simple dialog application, and am trying to accomplish two tasks with tooltips:

1 ) Get the tooltip to track with the mouse movement,i.e. follow the mouse cursor around, as long as it remains on the same control.
2) Get the tooltip to appear on a disabled control.

I have uploaded my simple project (VS2003, for maximum compatibility :)) to http://www.yousendit.com/download/bVlBWGJDd0lCSWRFQlE9PQ, please download it and take a look.

FYI, here is the code I am using to create and display the tooltip:

BOOL CEE_Tooltip_QDlg::OnInitDialog()

      VERIFY ( m_wndTooltip.Create ( this ) );

      VERIFY ( m_wndTooltip.AddTool ( GetDlgItem ( IDC_MYCONTROL ), LPSTR_TEXTCALLBACK ) );
      VERIFY ( m_wndTooltip.AddTool ( GetDlgItem ( IDC_EDIT1 ), LPSTR_TEXTCALLBACK ) ); // Disabled edit control

      // ...

void CEE_Tooltip_QDlg::OnNeedText ( NMHDR* pnmh, LRESULT* pResult )
      TOOLTIPTEXT* pttt = ( TOOLTIPTEXT* ) pnmh;
      // If the tooltip that this message has been sent for is our tooltip...
      if ( pttt->hdr.hwndFrom == m_wndTooltip.m_hWnd )
            // Find the string that maps to the window we are displaying the tooltip for ( stored in pttt->hdr.idFrom ).
            m_strTooltipText = _T("This is a long tooltip that has come from CEE_Tooltip_QDlg::OnNeedText");
            pttt->lpszText = ( LPTSTR ) ( LPCTSTR ) m_strTooltipText;

Can someone please tell me how to achieve these two tasks?  I simply cannot find anything on the internet about this.

  • 9
  • 6
3 Solutions
> I simply cannot find anything on the internet about this.

Then you didn't search in Msdn or Google groups, as it has been answered hundreds of times.
See Tracking Tooltips sample from Msdn  and Rect Tooltips...
mrwad99Author Commented:
I have searched in numerous places, and none of the code I have found works.

Take this example:


Following the posted code and recommended change, I still get no tracking tooltip.  No sample on MSDN, codeproject, codeguru or any other site I am familiar with has a *working example* of getting a tooltip to move with the mouse.

If you have seen one, or you know how to solve this, then please do tell.

AndyAinscowFreelance programmer / ConsultantCommented:
Instead of the individual controls have the tooltip linked to the dialog itself.
As the mouse moves around on the dialog you should be able to preview the mouse message, test if the cursor is over a control then show/hide/move the tooltip as required.

(I've had to resort to that myself some time ago - it does work but I don't think it is elegant however).
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

mrwad99Author Commented:
OK ok I managed to get the sample athttp://msdn.microsoft.com/en-us/library/bb760252(VS.85).aspx#tooltip_sample_trackingfor tracking tooltips working.  A bit messy but I should be able to tidy it up using CTooltipCtrl instead of the raw Win32 stuff.

Now I just need to get the tooltips to be displayed on disabled controls...

Ideas anyone?
mrwad99Author Commented:
Hi Andy!

Long time no, er, type!  I hope you are well.

Yeah, that is what the sample at MSDN does (the tooltip tracks over the whole dialog); I was just thinking how to get it to work for individual controls who have had tooltips added via CTooltipCtrl::AddTool()...

The first thought I had was have a common CWnd derived class from which I derive all controls from, then I can test whether the mouse is over it or not and show/hide appropriately.  Although that might be a little overkill.

I will continue to play; if you can comment on this or on disabled controls then please do.
AndyAinscowFreelance programmer / ConsultantCommented:
:-)   Fine, thanks.

I think you will have problems with disabled controls - if I remember correctly they will not get mouse messages (a feature of windows ?).
Just have a customised control eg. CEdit based with a mouse move handler and a TRACE statement.  When it is disabled you will not have any output from the TRACE.  As you don't get any mouse messages then the native (MFC) tooltip will not be displayed.

<You could try to make a 'helper' class which wraps the tooltip and maintains a collection of windows/rects - only a few lines of code in each dialog to implement it, most of which would be like the default tooltip code>
mrwad99Author Commented:
OK, that is what I thought you would say.

I have discovered various shortcomings in the MSDN sample.  To start, for an unknown reason the tooltip does not appear initially until the mouse is moved over the dialog then off; when moving it back on for the second time the tracking tooltip appears.

I have circumvented this as follows:

        static BOOL b = FALSE;    // NEW
        if (!g_TrackingMouse)// The mouse has just entered the window.
            // Request notification when the mouse leaves.
            TRACKMOUSEEVENT tme = { sizeof(TRACKMOUSEEVENT) };
            tme.hwndTrack = hDlg;
            tme.dwFlags = TME_LEAVE;

            // Activate the ToolTip.
            ::SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&g_toolItem);

            // NEW CODE FROM HERE
            g_TrackingMouse = TRUE;
            if ( !b )
                ::SendMessage ( this->m_hWnd, WM_MOUSELEAVE, 0, 0 );
                b = TRUE;

By forcing the tooltip to be deactivated after activation, it appears to work instantly, i.e. the first mouse movement detected displays the tooltip.

I wanted to tidy the MSDN code up using CTooltipCtrl.  So the first thing I did was create myself a CTooltipCtrl

    /*CTooltipCtrl */m_wndTTMSDN.Create ( this, TTF_TRACK | TTF_ABSOLUTE );

and update the global HWND to be the HWND of this object

I found that this did not work.  The problem is in that AddTool, the HWND member of the TOOLINFO structure used internally sets the HWND member to be the parent HWND of the window passed, which is NULL.  So we have to use the MSDN way of constructing the TOOLINFO and calling SendMessage()...

Also, regarding CTooltipCtrl in general, if we look at

_AFXCMN_INLINE void CToolTipCtrl::Activate(BOOL bActivate)
    { ASSERT(::IsWindow(m_hWnd));  ::SendMessage(m_hWnd, TTM_ACTIVATE, bActivate, 0L); }

we see that there is no LPARAM.  The MSDN sample linked to previously uses the following code to activate the tooltip

::SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)TRUE, (LPARAM)&g_toolItem);

With g_hwndTrackingTT as the HWND of my CTooltipCtrl as above, I cannot replace the SendMessage call with

    m_wndTTMSDN.Activate ( TRUE );

as it does not work; presumably due to the lack of TOOLINFO (indeed, even with SendMessage and 0 as LPARAM, it still fails).


    m_wndTTMSDN.UpdateTipText ( coords, this );

does not work when setting the text of the tooltip to be the cursor position;

    ::SendMessage(g_hwndTrackingTT, TTM_SETTOOLINFO, 0, (LPARAM)&g_toolItem);

must be used.  Internally, UpdateTipText sends a TTM_UPDATETIPTEXT, not a TTM_SETTOOLINFO...

I post most of the above as a summary of my findings, but do you have any comments anyone?

mrwad99Author Commented:
Disabled controls tooltips - I have the answer!


I had previously came across this but rejected it as it did not work.  The problem was that I had

BOOL CEE_Tooltip_QDlg::PreTranslateMessage(MSG* pMsg)
    static CWnd* arrayC [] = { GetDlgItem ( IDC_EDIT1 ) };
    HandleTooltipsActivation ( pMsg, this, arrayC, 1, &m_wndTooltip );
    m_wndTooltip.RelayEvent ( pMsg ); // ARGHHHHHH - SIN CITY!
    return CDialog::PreTranslateMessage(pMsg);

where m_wndTooltip is a  tooltip.  The problem was that the call to  m_wndTooltip.RelayEvent ( pMsg ) was stopping the tooltip appearing; without this call it all works just dandy :)

Even more interesting is the idea of wrapping this in a class -


which handles it all beautifully, simply beautifully!

So after any closing comments I guess I can close this question!
AndyAinscowFreelance programmer / ConsultantCommented:
Does the tip follow the cursor even if you don't move the cursor off the control ?

(I had a call m_tooltip.Update() after the RelayEvent() in my implentation).
mrwad99Author Commented:
Sorry Andy I am not with you on that; what part are you referring to?
AndyAinscowFreelance programmer / ConsultantCommented:
In the PreTranslateMsg, after calling the RelayEvent of the tip control I called the update.  The tip would then follow the cursor even if I kept the cursor on the same control.
mrwad99Author Commented:
Now that is interesting; it is effectively a form of tracking tooltip isn't it!  The downside is that if the mouse keeps moving, the tooltip never gets unactivated, even after moving off the control with which it was associated...

Are you aware of this?
AndyAinscowFreelance programmer / ConsultantCommented:
It does with me ;-)
mrwad99Author Commented:
Agreed.  The problem is when I use the custom tooltip class linked to above in the second link; when I have the override of RelayEvent this problem is encountered.  Commenting it out removes the problem.

Any ideas why this is?
AndyAinscowFreelance programmer / ConsultantCommented:
>>Any ideas why this is?

No, your guess would be as good as mine.  I would have to study the code of that class AND try to find out just what the CTooltip class::RelayEvent function is doing.
mrwad99Author Commented:
OK thats fine.  Overall, I am pleased with the answers that have been given here, and for the purposes of aiding future searchers, I will accept this summary as the overall answer, splitting the points between yourself Andy and Castorix.

Tracking tooltips:

The example at


shows how to achieve this where the tooltip text is updated continually.  This is nice, but if not required, the comment by AndyAinscow (http:Q_23797433.html#a22702786) is perfectly acceptable:

BOOL CDialogAppDlg::PreTranslateMessage(MSG* pMsg)
    m_wndToolTip.RelayEvent (pMsg);
    return CDialog::PreTranslateMessage(pMsg);

Tooltips on Disabled controls:

As commented at http:Q_23797433.html#a22702350; the CodeGuru articles show both a standalone function and a wrapper class to achieve this.  As noted above though, there are some issues with calling Update() on the tooltip within PreTranslateMessage when using the custom tooltip class.  I have not looked into those as yet.

Thanks again both :)

Featured Post

[Webinar] Improve your customer journey

A positive customer journey is important in attracting and retaining business. To improve this experience, you can use Google Maps APIs to increase checkout conversions, boost user engagement, and optimize order fulfillment. Learn how in this webinar presented by Dito.

  • 9
  • 6
Tackle projects and never again get stuck behind a technical roadblock.
Join Now