Solved

Tooltips: tracking and working for disabled controls - how?

Posted on 2008-10-08
16
1,222 Views
Last Modified: 2013-12-03
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()
{
      CDialog::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.

TIA
0
Comment
Question by:mrwad99
  • 9
  • 6
16 Comments
 
LVL 2

Assisted Solution

by:Castorix
Castorix earned 200 total points
ID: 22691815
> 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...
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22697254
I have searched in numerous places, and none of the code I have found works.

Take this example:

 http://groups.google.com/group/microsoft.public.win32.programmer.ui/browse_thread/thread/2c883f6081350a9a/72afac3b5bc9dc68?lnk=st&q=tracking+tooltip

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.

Thanks.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 22701101
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).
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22701104
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?
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22701118
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.
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 22701541
:-)   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>
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22701964
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;
            TrackMouseEvent(&tme);

            // 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).

Also,

    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?



0
 
LVL 19

Author Comment

by:mrwad99
ID: 22702350
Disabled controls tooltips - I have the answer!

http://www.codeguru.com/cpp/controls/controls/tooltipcontrols/article.php/c2277

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 -

http://www.codeguru.com/cpp/controls/controls/tooltipcontrols/comments.php/c2277/?thread=29452

which handles it all beautifully, simply beautifully!

So after any closing comments I guess I can close this question!
0
Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 300 total points
ID: 22702786
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).
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22702813
Sorry Andy I am not with you on that; what part are you referring to?
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 22702961
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.
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22703035
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?
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 22703789
It does with me ;-)
0
 
LVL 19

Author Comment

by:mrwad99
ID: 22704104
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?
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 22709006
>>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.
0
 
LVL 19

Accepted Solution

by:
mrwad99 earned 0 total points
ID: 22709893
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

http://msdn.microsoft.com/en-us/library/bb760252(VS.85).aspx#tooltip_sample_tracking

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);
    m_wndToolTip.Update();
    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 :)
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Fibonacci challenge 11 82
How to convert MFC::CString to UTF8 wchar_t* 10 94
unix example issues 18 46
Not needed 13 54
Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now