About ToolTip Controls


ToolTips are hidden most of the time. They appear automatically, or pop up, when the user pauses the mouse pointer over a tool. The ToolTip appears near the pointer and disappears when the user clicks a mouse button or moves the pointer away from the tool.

ToolTip Behavior and Appearance

ToolTip controls can display a single line of text or multiple lines. Their corners can be rounded or square. They might or might not have a stem that points to the tools like a cartoon balloon. ToolTip text can be stationary or can move with the mouse pointer, called tracking. Stationary text can be displayed adjacent to a tool or it can be displayed over a tool, which is referred to as in-place. Standard ToolTips are stationary, display a single line of text, have square corners, and have no stem pointing to the tool.

Tracking ToolTips, which are supported by version 4.70 of the common controls, change position on the screen dynamically. By rapidly updating the position, these ToolTip controls appear to move smoothly, or "track." These are useful when you want ToolTip text to follow the position of the mouse pointer as it moves. For more information about tracking ToolTips and an example with code that shows how you create them, see Tracking ToolTips .

Multiline ToolTips, which are also supported by version 4.70 of the common controls, display text on more than one line. These are useful for displaying lengthy messages. For more information and an example that shows how to create multiline ToolTips, see Multiline ToolTips .

Balloon ToolTips are displayed in a cartoon-style "balloon," with rounded corners and a stem pointing to the tool. They can be either single-line or multiline. The following illustration shows a multiline balloon ToolTip with the stem and rectangle in their default positions. For more information about balloon ToolTips and an example that shows how you create them, see Balloon ToolTips .

Sometimes text strings that are long enough to display useful information get clipped because they are too long to be displayed completely in a small window or frame. This diminishes the usefulness of the text strings. In-place ToolTips are used to display text strings for objects that have been clipped, such as the folder names shown on the right in the following graphic. For an example that shows how to create in-place ToolTips, see In-Place ToolTips .

The cursor must hover over a tool for a period of time before the ToolTip is displayed. The default duration of this timeout is controlled by the user's double click time and is typically about one-half second. To specify a non-default timeout value, send the ToolTip control a TTM_SETDELAYTIME message.

Creating ToolTip Controls

To create a ToolTip control, call CreateWindowEx and specify the TOOLTIPS_CLASS window class. This class is registered when the common control dynamic-link library (DLL) is loaded. To ensure that this DLL is loaded, include the InitCommonControlsEx function in your application. You must explicitly define a ToolTip control as topmost. Otherwise, it might be covered by the parent window. The following code fragment shows how to create a ToolTip control.

HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                            WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            CW_USEDEFAULT, CW_USEDEFAULT,
                            hwndParent, NULL, hinstMyDll,
                            NULL);

SetWindowPos(hwndTip, HWND_TOPMOST,0, 0, 0, 0,
             SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);

The window procedure for the ToolTip control automatically sets the size, position, and visibility of the control. The height of the ToolTip window is based on the height of the font currently selected into the device context for the ToolTip control. The width varies based on the length of the string currently in the ToolTip window.

Activating ToolTip Controls

A ToolTip control can be either active or inactive. When it is active, the ToolTip text appears when the mouse pointer is on a tool. When it is inactive, the ToolTip text does not appear, even if the pointer is on a tool. The TTM_ACTIVATE message activates and deactivates a ToolTip control.

Supporting Tools

A ToolTip control can support any number of tools. To support a particular tool, you must register the tool with the ToolTip control by sending the control the TTM_ADDTOOL message. The message includes the address of a TOOLINFO structure, which provides information the ToolTip control needs to display text for the tool. The uID member of the TOOLINFO structure is defined by the application. Each time you add a tool, your application provides a unique identifier. The cbSize member of the TOOLINFO structure is required, and must specify the size of the structure.

A ToolTip control supports tools implemented as windows (such as child windows or control windows) and as rectangular areas within a window's client area. When you add a tool implemented as a rectangular area, the hwnd member of the TOOLINFO structure must specify the handle to the window that contains the area, and the rect member must specify the client coordinates of the area's bounding rectangle. In addition, the uID member must specify the application-defined identifier for the tool.

When you add a tool implemented as a window, the uID member of the TOOLINFO structure must contain the window handle to the tool. Also, the uFlags member must specify the TTF_IDISHWND value, which tells the ToolTip control to interpret the uID member as a window handle.

Displaying Text

When you add a tool to a ToolTip control, the lpszText member of the TOOLINFO structure must specify the address of the string to display for the tool. After you add a tool, you can change the text using the TTM_UPDATETIPTEXT message.

If the high-order word of lpszText is zero, the low-order word must be the identifier of a string resource. When the ToolTip control needs the text, the system loads the specified string resource from the application instance identified by the hinst member of the TOOLINFO structure.

If you specify the LPSTR_TEXTCALLBACK value in the lpszText member, the ToolTip control notifies the window specified in the hwnd member of the TOOLINFOstructure whenever the ToolTip control needs to display text for the tool. The ToolTip control sends the TTN_GETDISPINFO notification message to the window. The message includes the address of a NMTTDISPINFO structure, which contains the window handle as well as the application-defined identifier for the tool. The window examines the structure to determine the tool for which text is needed, and it fills the appropriate structure members with information that the ToolTip control needs in order to display the string.

Note   The maximum length for standard ToolTip text is 80 characters. For more information, see the NMTTDISPINFO structure. Multiline ToolTip text can be longer.

Many applications create toolbars containing tools that correspond to menu commands. For such tools, it is convenient for the ToolTip control to display the same text as the corresponding menu item. The system automatically strips the ampersand (&) accelerator characters from all strings passed to a ToolTip control, unless the control has the TTS_NOPREFIX style.

To retrieve the text for a tool, use the TTM_GETTEXT message.

Messaging and Notification

ToolTip text is normally displayed when the mouse pointer hovers over an area, typically the rectangle defined by a tool such as a button control. However, Microsoft® Windows® only sends mouse-related messages to the window that contains the pointer, not the ToolTip control itself. Mouse-related information must be relayed to the ToolTip control in order for it to display the ToolTip text at the appropriate time and place.

You can have messages relayed automatically if:

If these two conditions are met, set the TTF_SUBCLASS flag in the uFlags member of the tool's TOOLINFO structure when you add the tool to the ToolTip control with TTM_ADDTOOL. The necessary mouse messages then will be relayed automatically to the ToolTip control.

Setting TTF_SUBCLASS to have mouse messages relayed to the control is sufficient for most purposes.However, it will not work in cases where there is no direct connection between the ToolTip control and the tool's window. For example, if a tool is implemented as a rectangular area in an application-defined window, the window procedure receives the mouse messages. Setting TTF_SUBCLASS is sufficient to ensure that they are passed to the control. However, if a tool is implemented as a system-defined window, mouse messages are sent to that window and are not directly available to the application. In this case, you must either subclass the window or use a message hook to access the mouse messages. You must then explicitly relay mouse messages to the ToolTip control with TTM_RELAYEVENT . For an example of how to use TTM_RELAYEVENT, see Tracking ToolTips .

When a ToolTip control receives a WM_MOUSEMOVE message, it determines whether the mouse pointer is in the bounding rectangle of a tool. If it is, the ToolTip control sets a timer. At the end of the time-out interval, the ToolTip control checks the position of the pointer to see if it has moved. If it hasn't, the ToolTip control retrieves the text for the tool and displays the ToolTip. The ToolTip control continues to show the window until it receives a relayed button-up or button-down message or until a WM_MOUSEMOVE message indicates that the pointer has moved outside the bounding rectangle of the tool.

A ToolTip control actually has three time-out durations associated with it. The initial duration is the length of time that the mouse pointer must remain stationary within the bounding rectangle of a tool before the ToolTip window is displayed. The reshow duration is the length of the delay before subsequent ToolTip windows are displayed when the pointer moves from one tool to another. The pop-up duration is the length of time that the ToolTip window remains displayed before it is hidden. That is, if the pointer remains stationary within the bounding rectangle afterthe ToolTip window is displayed, the ToolTip window is automatically hidden at the end of the pop-up duration. You can adjust all of the time-out durations by using the TTM_SETDELAYTIME message.

If an application includes a tool implemented as a rectangular area and the size or position of the control changes, the application can use the TTM_NEWTOOLRECT message to report the change to the ToolTip control. An application does not need to report size and position changes for a tool implemented as a window because the ToolTip control uses the tool's window handle to determine if the mouse pointer is on the tool, not the tool's bounding rectangle.

When a ToolTip is about to be displayed, the ToolTip control sends the owner window a TTN_SHOW notification message. The owner window receives a TTN_POP notification when a ToolTip is about to be hidden. Each notification is sent in the context of a WM_NOTIFY message.

Hit Testing

The TTM_HITTEST message allows you to retrieve information that a ToolTip control maintains about the tool occupying a particular point. The message includes a TTHITTESTINFO structure that contains a window handle, the coordinates of a point, and the address of a TOOLINFO structure. The ToolTip control determines whether a tool occupies the point and, if it does, fills TOOLINFO with information about the tool.

Default Message Processing

The following table describes the messages handled by the window procedure for the ToolTip control.

Message Description
WM_CREATE Ensures that the ToolTip control has the WS_EX_TOOLWINDOW and WS_POPUP window styles. It also allocates memory and initializes internal variables.
WM_DESTROY Frees resources allocated for the ToolTip control.
WM_GETFONT Returns the handle of the font that the ToolTip control will use to draw text.
WM_MOUSEMOVE Hides the ToolTip window.
WM_PAINT Draws the ToolTip window.
WM_SETFONT Sets the handle of the font that the ToolTip control will use to draw text.
WM_TIMER Hides the ToolTip window if the tool has changed position or if the mouse pointer has moved outside the tool. Otherwise, it shows the ToolTip window.
WM_WININICHANGE Resets internal variables that are based on system metrics.

Using ToolTip Controls


This section contains examples that demonstrate how to create different types of ToolTips.

ToolTips for Rectangular Areas

The following example demonstrates how to create a standard ToolTip control and add a tool to it. The example creates a rectangular area, which consists of a window's entire client area, and then uses the TTM_ADDTOOL message to add a ToolTip control to the rectangular area. The TTF_SUBCLASS flag is set in the uFlags member of the TOOLINFO structure to have mouse messages automatically passed to the ToolTip control.

The output window for this sample looks like this.

Tracking ToolTips

Tracking ToolTips change position on the screen dynamically. They are supported by version 4.70 and later of the common controls. To create a tracking ToolTip, use the TTM_ADDTOOL message, including the TTF_TRACK flag in the uFlags member of the accompanying TOOLINFO structure.

Your application must manually activate and deactivate a tracking ToolTip by sending a TTM_TRACKACTIVATE message. Activation or deactivation also shows or hides the ToolTip, respectively. While a tracking ToolTip is active, your application must specify the location of the ToolTip by sending TTM_TRACKPOSITION messages to the ToolTip control. Because the application handles tasks such as positioning the ToolTip, tracking ToolTips do not use the TTF_SUBCLASS flag or the TTM_RELAYEVENT message.

The TTM_TRACKPOSITION message causes the ToolTip control to display the window using one of two placement styles:

Example

The following example demonstrates how to create a ToolTip control and assign a tool to it. The example specifies the main window's entire client area as the tool, but you could specify distinct portions of the client area or specify a different window altogether.

The example uses the TTM_ADDTOOL message to add the tool to the ToolTip control. The uFlags member of the TOOLINFO structure used in the example includes the TTF_ABSOLUTE flag. This flag causes the ToolTip control to display ToolTip text at the exact coordinates the application provides when it sends the TTM_TRACKPOSITION message. Without the TTF_ABSOLUTE flag, the ToolTip control chooses a location to display the ToolTip text based on the coordinates you provide. This causes ToolTip text to appear next to the corresponding tool, but not necessarily at the exact coordinates the application provided.

For additional information about using the TTM_TRACKPOSITION message, see Supporting Tracking ToolTips.

Supporting Tracking ToolTips

The following example is a simple window process function that supports tracking ToolTips. It requests the current position of the mouse pointer by using the GetCursorPos function and then adds 15 pixels to the x- and y-coordinates, so the ToolTip appears slightly below and to the right of the pointer. GetCursorPos returns the screen coordinates of the cursor in a POINT structure.

Note that the example relies on the value of a global variable, g_bIsVisible, to determine whether the application should send the TTM_TRACKPOSITION message. For the purpose of this example, g_bIsVisible is a Boolean variable that another function sets to TRUE upon sending the TTM_TRACKACTIVATE message to activate the ToolTip. This way, if the ToolTip is inactive, the additional overhead to calculate and send a message is not incurred.

Multiline ToolTips

Multiline ToolTips allow text to be displayed on more than one line. They are supported by version 4.70 and later of the common controls. Your application creates a multiline ToolTip by responding to a TTN_GETDISPINFO notification message. To force the ToolTip control to use multiple lines, send a TTM_SETMAXTIPWIDTH message, specifying the width of the display rectangle. Text that exceeds this width will wrap to the next line rather than widening the display region. The rectangle height will be increased as needed to accommodate the additional lines. The ToolTip control will wrap the lines automatically, or you can use a carriage return/line feed combination, \r\n, to force line breaks at particular locations.

Note that the text buffer specified by the szText member of the NMTTDISPINFO structure can accommodate only 80 characters. If you need to use a longer string, point the lpszText member of NMTTDISPINFO to a buffer containing the desired text.

The following code fragment is an example of a simple TTN_GETDISPINFO notification handler. It creates a multiline ToolTip by setting the display rectangle to 300 pixels and setting the lpszText member of NMTTDISPINFO to point to a buffer with the desired text.

Balloon ToolTips

Balloon ToolTips are similar to standard ToolTips, but are displayed in a cartoon-style "balloon" with a stem pointing to the tool. Balloon ToolTips can be either single-line or multiline. They are created and handled in much the same way as standard ToolTips.

The default position of the stem and rectangle is shown below. If the tool is too close to the top of the screen, the ToolTip appears below and to the right of the tool's rectangle. If the tool is too close to the right side of the screen, similar principles apply, but the ToolTip appears to the left of the tool's rectangle.

You can change the default positioning by setting the TTF_CENTERTIP flag in the uFlags member of the ToolTip's TOOLINFO structure. In that case, the stem normally will point to the center of the lower edge of the tool's rectangle, and the text rectangle will be displayed directly below the tool. The stem will attach to the text rectangle at the center of the upper edge. If the tool is too close to the bottom of the screen, the text rectangle will be centered above the tool, and the stem will attach to the center of the lower edge.

If you want to specify where the stem points, set the TTF_TRACK flag in the uFlags member of the ToolTip's TOOLINFO structure. You then specify the coordinate by sending a TTM_TRACKPOSITION message, with the x- and y-coordinates in the lParam value. If TTF_CENTERTIP is also set, the stem still points to the position specified by the TTM_TRACKPOSITION message.

The following code fragment illustrates how to implement a centered balloon ToolTip.

Balloon ToolTips for Status Bar Icons

A nonintrusive way to display an explanatory message for a status bar icon is to implement a balloon ToolTip with its stem pointing to the icon. The ToolTip will disappear when clicked, but you can also specify a time-out value. The ToolTip will look similar to the following illustration.

For a detailed discussion of the status bar, see the The Taskbar documentation.

The following code fragment illustrates how to add a balloon ToolTip to a status bar icon.

To display a balloon ToolTip, you need to set the NIF_INFO flag in the NOTIFYICONDATA structure, and use the szInfo and uTimeout members to specify the ToolTip text and time-out duration.

Show Example

In-Place ToolTips

In-place ToolTips are used to display text strings for objects that have been clipped, such as the folder names shown below in Microsoft® Windows® Explorer. In this illustration, information concerning the scribble folder is shown in the tooltip.

The difference between ordinary and in-place ToolTips is positioning. By default, when the mouse pointer hovers over a region that has a ToolTip associated with it, the ToolTip is displayed adjacent to the region. However, ToolTips are windows, and they can be positioned anywhere you choose by calling SetWindowPos . Creating an in-place ToolTip is a matter of positioning the ToolTip window so that it overlays the text string.

Positioning an In-Place ToolTip

You need to keep track of three rectangles when positioning an in-place ToolTip:

The three rectangles are shown schematically in the following illustration. The hidden portion of the label text is indicated by a gray background.

To create an in-place ToolTip, you must position the ToolTip text rectangle so that it overlays the label text rectangle. The procedure for aligning the two rectangles is relatively straightforward:

  1. Define the label text rectangle.
  2. Position the ToolTip window so that the ToolTip text rectangle overlays the label text rectangle

In practice, it is usually sufficient to align the upper-left corner of the two text rectangles. Attempting to resize the ToolTip text rectangle to exactly match the label text rectangle could cause problems with the ToolTip display.

The problem with this simple scheme is that you can't position the ToolTip text rectangle directly. Instead, you must position the ToolTip window rectangle just far enough above and to the left of the label text rectangle so that the corners of the two text rectangles coincide. In other words, you need to know the offset between the ToolTip window rectangle and its enclosed text rectangle. In general, there is no simple way to determine this offset.

Using TTM_ADJUSTRECT to Position a ToolTip

Common controls version 5.80 simplifies the use of in-place ToolTips by the addition of a new message, TTM_ADJUSTRECT . Send this message with the coordinates of the label text rectangle that you want the ToolTip to overlay, and it will return the coordinates of an appropriately positioned ToolTip window rectangle.

The following code fragment illustrates how to use TTM_ADJUSTRECT in a TTN_SHOW handler to display an in-place ToolTip. Your application indicates that the label text is truncated by setting the private fMyStringIsTruncated variable to TRUE. The handler calls an application-defined function, GetMyItemRect, to retrieve the label text rectangle. This rectangle is passed to the ToolTip control with TTM_ADJUSTRECT, which returns the corresponding window rectangle. SetWindowPos is then called to position the ToolTip over the label.

This example does not change the size of the ToolTip, just its position. The two text rectangles will be aligned at their upper-left corners, but not necessarily with the same dimensions. In practice, the difference is usually small, and this approach is recommended for most purposes. While you can, in principle, use SetWindowPos to resize as well as reposition the ToolTip, doing so might have unpredictable consequences.