News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Tooltips R EZ!

Started by NoCforMe, November 12, 2011, 05:30:52 AM

Previous topic - Next topic

NoCforMe

Just finished a li'l testbed, pretty much in one sitting, that gets me up and running on tooltips. Even though it seemed daunting at first, and really complicated, it turns out to be not too hard after all.

So I wanted to share my "recipe" with any of you who might be wanting to try this. I got most of my information from MSDN, but it turns out that in addition to there being gaps in their explanations, there's also some erroneous stuff there. The attached .zip has a little program that shows how to implement tooltips.

Here's my recipe:

1.. Prepare the Common Controls DLL by calling InitCommonControlsEx(), specifying ICC_BAR_CLASSES (at least; you can add other classes of controls as well.) (This is something that's not mentioned at all in the MSDN info, presumably because this is already done for the programmer using Visual C or .net or whatever.)

2. Create the toolbar window with the TBSTYLE_LIST and TBSTYLE_TOOLTIPS styles.

3. Create the toolbar as usual, loading bitmap(s) (if any), creating buttons, etc.

4. Set the TBSTYLE_EX_MIXEDBUTTONS "extended style" (by sending a SETEXTENDEDSTYLE message to the control).

5. Handle the TTN_NEEDTEXT (alias TTN_GETDISPINFO, same thing) notification. This will come as a code in a WM_NOTIFY message. Look at the control ID in the NMHDR header of the message; if it matches your toolbar button, then all you need to do is to specify the text for the tooltip. (This can be done either by copying the text into the NMTTDISPINFO structure itself, or by giving it the address of a string in your application (or as the handle to a string resource). You should also set the TTF_DI_SETITEM flag (in the "uFlags" member) so that Windows will save the text and not bother you again.

Here's the (apparently) erroneous MSDN information:

  • They tell us to put pointers to tooltip text in the "iString" members of the TBBUTTON structures, and to send the TB_SETMAXTEXTROWS message to set the max. # of rows to zero. Both of these things appear to be completely unnecessary (at least my tooltips work fine without them). It seemed really silly to put pointers to the strings in these structures when creating the tooltips, and setting the text in the notification handler.

  • It is also not necessary to respond to the TBN_GETINFOTIP notification (only TTN_NEEDTEXT/TTN_GETDISPINFO needs to be handled).
Both of these mistaken instructions come from an otherwise fairly comprehensive and helpful page on tooltips.

I also came up with a really simple way to initialize all those toolbar strings. If you have a lot of toolbar buttons, it can be a real pain in the ass to initialize all of them in the message handler. The dumb way would be something like



MOV EDX, lParam ;--> NMTTDISPINFO struct.
MOV EAX, [EDX + NMHDR.idFrom] ;Could be the ID of one of our controls.
CMP EAX, $controlID1
JE do_control1
CMP EAX, $controlID2
JE do_control2

... etc. ...

do_control1:
LEA EAX, TextForToolbarButton1
MOV [EDX + NMTTDISPINFO.lpszText], EAX ;Ptr. to tooltip text.
MOV [EDX + NMTTDISPINFO.uFlags], TTF_DI_SETITEM ;Don't bother me again!



which amounts to a whole lot of IF-ELSEing for all those buttons!

Use indexing instead:



;===== Toolbar button IDs: =====
$TBbutton1 EQU  1500
$TBbutton2 EQU  1501
$TBbutton3 EQU  1502
$TBbutton4 EQU  1503
$TBbutton5 EQU  1504
$TBbutton6 EQU  1505
$TBbutton7 EQU  1506
$TBbutton8 EQU  1507


ToolTipTextPtrs DD BTN1text, BTN2text, BTN3text, BTN4text
DD BTN5text, BTN6text, BTN7text, BTN8text

BTN1text DB "whole note", 0
BTN2text DB "half note", 0
BTN3text DB "quarter note", 0
BTN4text DB "8th note", 0
BTN5text DB "whole rest", 0
BTN6text DB "half rest", 0
BTN7text DB "quarter rest", 0
BTN8text DB "8th rest", 0

(message handler for WM_NOTIFY:)

MOV EDX, lParam ;--> NMTTDISPINFO struct.
CMP [EDX + NMHDR.code], TTN_NEEDTEXT ;aka TTN_GETDISPINFO
JNE dodefault
MOV EAX, [EDX + NMHDR.idFrom] ;Could be the ID of one of our controls.
CMP EAX, $TBbutton1
JB dodefault
CMP EAX, $TBbutton8
JA dodefault

; At this point, we have a TTN_NEEDTEXT message for one of our buttons:
SUB EAX, $TBbutton1 ;Get offset from 1st button ID:
SHL EAX, 2 ;convert to DWORD offset
MOV EAX, [EAX + OFFSET ToolTipTextPtrs]
MOV [EDX + NMTTDISPINFO.lpszText], EAX ;Ptr. to tooltip text.
MOV [EDX + NMTTDISPINFO.uFlags], TTF_DI_SETITEM ;Don't bother me again!
RET ;No particular return value needed.



This works because all the toolbar button IDs are in a contiguous block, so I can use the ID passed in as an index into the list of pointers. Easy peasy!




jj2007

Nice work :U
For tooltips & Unicode see this thread.

NoCforMe

I have to revise my "recipe". Tooltips are even easier than I described.

If you set the styles as I explained, and set the iString member of the TBBUTTON structure to point to your tooltip text strings, you don't even need to mess around at all with any notifications. (I guess you might want to use the notifications if you need to implement dynamic tooltip strings where the tooltips change during program execution.)

jj2007

The really lazy boyz use this...

Quote  CASE WM_CREATE
   ...
   ToolTips TTS_BALLOON
   ToolTips hEdit, "Type something useful"
   ToolTips hButton1, "Click on this button"