Recenty a colleague of mine came up and asked if it’s possible to display tooltips for toolbar buttons and other controls without much difficulty. So I gave him the solution and also decided to post it here for anyone who doesn’t know.
When a tooltip text is to be displayed the framework sends a TTN_NEEDTEXT notification, so it’s upto the handler of the event to pass a text to the event. Add two message map entries to your dialog message map section…
BEGIN_MESSAGE_MAP(CSomeDlg, CDialog) ON_NOTIFY_EX_RANGE( TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText ) ON_NOTIFY_EX_RANGE( TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText ) END_MESSAGE_MAP()
Add a function to your your CSomeDlg class…
BOOL CSomeDlg::OnToolTipText(UINT, NMHDR* pNMHDR, LRESULT* pResult) { // OnNeedText should only be called for TTN_NEEDTEXT notifications! ASSERT(pNMHDR->code == TTN_NEEDTEXTA || pNMHDR->code == TTN_NEEDTEXTW); // need to handle both ANSI and UNICODE versions of the message TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR; TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR; CString strTipText; UINT nID = pNMHDR->idFrom; if ( pNMHDR->code == TTN_NEEDTEXTA && (pTTTA->uFlags & TTF_IDISHWND ) || pNMHDR->code == TTN_NEEDTEXTW && (pTTTW->uFlags & TTF_IDISHWND )) { // idFrom is actually the HWND of the tool nID = ((UINT)(WORD)::GetDlgCtrlID((HWND)nID)); } if (nID != 0) // will be zero on a separator { strTipText.LoadString( nID ); } // Handle conditionally for both UNICODE and non-UNICODE apps #ifndef _UNICODE if (pNMHDR->code == TTN_NEEDTEXTA) lstrcpyn(pTTTA->szText, strTipText, _countof(pTTTA->szText)); else _mbstowcsz(pTTTW->szText, strTipText, _countof(pTTTW->szText)); #else if (pNMHDR->code == TTN_NEEDTEXTA) _wcstombsz(pTTTA->szText, strTipText, _countof(pTTTA->szText)); else lstrcpyn(pTTTW->szText, strTipText, _countof(pTTTW->szText)); #endif *pResult = 0; // Bring tooltip to front ::SetWindowPos( pNMHDR->hwndFrom, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOMOVE ); return TRUE; // message was handled }
Now tooltips should start appearing…
Well this is not limited just to dialog’s, can be used with any window provided you have provided a string resource corresponding to your control’s id. If you are using visual studio resource editor you have the provision to enter a tooltip text. Don’t forget to call EnableTooltips().
Except for unicode handling, other stuffs are pretty straight forward, easy for you understand. Just in case you are having trouble decrypting 😉 ask me!
A similar sample can be found in MSDN… 😉
Yes clarke that’s true, you can safely use TTN_NEEDTEXT instead of TTN_NEEDTEXTA and TTN_NEEDTEXTW. Since all MSDN samples use both the “A” and “W” explicitly I too thought of including it.
I’m confused why you use TTN_NEEDTEXTW & TTN_NEEDTEXTA instead of simply using TTN_NEEDTEXT and letting the preprocessor handle things?
If you were writing a control which disappears into an opaque DLL, then I could understand – but it seems over the top here.
Other than that, it looks like very steal^h^h^h^h^hreusable code!
Iain.