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 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
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
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

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

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
To create a ToolTip control, call
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.
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
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
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.
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
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
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
To retrieve the text for a tool, use the
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
When a ToolTip control receives a
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
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
When a ToolTip is about to be displayed, the ToolTip control sends the owner
window a
The
The following table describes the messages handled by the window procedure for the ToolTip control.
| Message | Description |
|---|---|
| Ensures that the ToolTip control has the WS_EX_TOOLWINDOW and |
|
| Frees resources allocated for the ToolTip control. | |
| Returns the handle of the font that the ToolTip control will use to draw text. | |
| Hides the ToolTip window. | |
| Draws the ToolTip window. | |
| Sets the handle of the font that the ToolTip control will use to draw text. | |
| 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. | |
| Resets internal variables that are based on system metrics. |
This section contains examples that demonstrate how to create different types of ToolTips.
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
/* CREATE A TOOLTIP CONTROL OVER THE ENTIRE WINDOW AREA */
void CreateMyTooltip (HWND hwnd)
{
// struct specifying control classes to register
INITCOMMONCONTROLSEX iccex;
HWND hwndTT; // handle to the ToolTip control
// struct specifying info about tool in ToolTip control
TOOLINFO ti;
unsigned int uid = 0; // for ti initialization
char strTT[30] = "This is your ToolTip string.";
LPTSTR lptstr = strTT;
RECT rect; // for client area coordinates
/* INITIALIZE COMMON CONTROLS */
iccex.dwICC = ICC_WIN95_CLASSES;
iccex.dwSize = sizeof(INITCOMMONCONTROLSEX);
InitCommonControlsEx(&iccex);
/* CREATE A TOOLTIP WINDOW */
hwndTT = CreateWindowEx(WS_EX_TOPMOST,
TOOLTIPS_CLASS,
NULL,
WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
hwnd,
NULL,
ghThisInstance,
NULL
);
SetWindowPos(hwndTT,
HWND_TOPMOST,
0,
0,
0,
0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
/* GET COORDINATES OF THE MAIN CLIENT AREA */
GetClientRect (hwnd, &rect);
/* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_SUBCLASS;
ti.hwnd = hwnd;
ti.hinst = ghThisInstance;
ti.uId = uid;
ti.lpszText = lptstr;
// ToolTip control will cover the whole window
ti.rect.left = rect.left;
ti.rect.top = rect.top;
ti.rect.right = rect.right;
ti.rect.bottom = rect.bottom;
/* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */
SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
}
The output window for this sample looks like this.

Tracking ToolTips change position on the screen dynamically. They are
supported by
Your application must manually activate and deactivate a tracking ToolTip
by sending a
The TTM_TRACKPOSITION message causes the ToolTip control to display the window using one of two placement styles:
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
For additional information about using the TTM_TRACKPOSITION message, see Supporting Tracking ToolTips.
HWND WINAPI CreateTT(HWND hwndOwner)
{
INITCOMMONCONTROLSEX icex;
HWND hwndTT;
TOOLINFO ti;
// Load the ToolTip class from the DLL.
icex.dwSize = sizeof(icex);
icex.dwICC = ICC_BAR_CLASSES;
if(!InitCommonControlsEx(&icex))
return NULL;
// Create the ToolTip control.
hwndTT = CreateWindow(TOOLTIPS_CLASS, TEXT(""),
WS_POPUP,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, (HMENU)NULL, g_hinst,
NULL);
// Prepare TOOLINFO structure for use as tracking ToolTip.
ti.cbSize = sizeof(TOOLINFO);
ti.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
ti.hwnd = hwndOwner;
ti.uId = (UINT)g_hwndMain;
ti.hinst = g_hinst;
ti.lpszText = LPSTR_TEXTCALLBACK;
ti.rect.left = ti.rect.top = ti.rect.bottom = ti.rect.right = 0;
// Add the tool to the control, displaying an error if needed.
if(!SendMessage(hwndTT,TTM_ADDTOOL,0,(LPARAM)&ti)){
MessageBox(hwndOwner,"Couldn't create the ToolTip control.",
"Error",MB_OK);
return NULL;
}
// Activate (display) the tracking ToolTip. Then, set a global
// flag value to indicate that the ToolTip is active, so other
// functions can check to see if it's visible.
SendMessage(hwndTT,TTM_TRACKACTIVATE,(WPARAM)TRUE,(LPARAM)&ti);
g_bIsVisible = TRUE;
return(hwndTT);
}
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
Note that the example relies on the value of a global variable,
g_bIsVisible, to determine whether the application should send the
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,
WPARAM wParam, LPARAM lParam)
{
switch(msg){
case WM_MOUSEMOVE:
if(g_bIsVisible){
#define X_OFFSET 15
#define Y_OFFSET X_OFFSET
SendMessage(g_hwndTT,
TTM_TRACKPOSITION,
0,
(LPARAM)MAKELPARAM(GET_X_LPARAM(lParam) + X_OFFSET,
GET_Y_LPARAM(lParam) + Y_OFFSET));
}
break;
/*
*
* Other standard window messages can be handled here.
*
*/
}
return 0;
}
Multiline ToolTips allow text to be displayed on more than one line. They
are supported by
Note that the text buffer specified by the szText member of the
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.
char szLongMessage[ ] =
"This is a long message for the ToolTip, which will automatically "
"be wrapped when it exceeds the maximum tip width. "
"Alternatively, you can use a \r\n"
"carriage return/line feed combination\r\n"
"to force line breaks at specific\r\n"
"locations.";
switch (lpnmhdr->code) {
case TTN_GETDISPINFO:
lpttd = (LPNMTTDISPINFO)lpnmhdr;
SendMessage(lpnmhdr->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 300);
lpttd->lpszText = szLongMessage;
return 0;
...
//Other notification handlers go here, as needed.
}
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
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
The following code fragment illustrates how to implement a centered balloon ToolTip.
hwndToolTips = CreateWindow(TOOLTIPS_CLASS,
NULL,
WS_POPUP | TTS_NOPREFIX | TTS_BALLOON,
0, 0,
0, 0,
NULL, NULL,
g_hinst,
NULL);
if (hwndTooltip)
{
// Do the standard ToolTip coding.
TOOLINFO ti;
ti.cbSize = sizeof(ti);
ti.uFlags = TTF_TRANSPARENT | TTF_CENTERTIP;
ti.hwnd = hwnd;
ti.uId = 0;
ti.hinst = NULL;
ti.lpszText = LPSTR_TEXTCALLBACK;
GetClientRect(hwnd, &ti.rect);
SendMessage(hwndToolTips, TTM_ADDTOOL, 0, (LPARAM) &ti );
}
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 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
Show Example
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
NOTIFYICONDATA IconData = {0};
IconData.cbSize = SIZEOF(IconData);
IconData.hWnd = hwndNI;
IconData.uFlags = NIF_INFO;
HRESULT hr = StringCchCopy(IconData.szInfo, ARRAYSIZE(IconData.szInfo), TEXT("Your message text goes here."));
if(FAILED(hr))
{
// TODO: Write an error handler in case the call to StringCchCopy fails.
}
IconData.uTimeout = 15000; // in milliseconds
Shell_NotifyIcon(NIM_MODIFY, &IconData);
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
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:
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.
Common controls
The following code fragment illustrates how to use TTM_ADJUSTRECT in
a
case TTN_SHOW:
if (fMyStringIsTruncated) {
RECT rc;
GetMyItemRect(&rc);
SendMessage(hwndToolTip, TTM_ADJUSTRECT, TRUE, (LPARAM)&rc);
SetWindowPos(hwndToolTip,
NULL,
rc.left, rc.top,
0, 0,
SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
}
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