Click to Rate and Give Feedback
MSDN
MSDN Library
User Interface
Windows Controls
Control Library
ToolTip
 Using ToolTip Controls

  Switch on low bandwidth view
Using ToolTip Controls

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

Creating a ToolTip for a Control

The following example function creates a ToolTip and associates it with the control whose resource ID is passed in.

BOOL CreateToolTip(int toolID, HWND hDlg, WCHAR* pText)
{
    // toolID:  the resource ID of the control.
    // hDlg:    the handle of the dialog box.
    // pText:   the text that appears in the ToolTip.
    // g_hInst: the global instance handle.
    
    if (!toolID || !hDlg || !pText)
    {
        return FALSE;
    }
    // Get the window of the tool.
    HWND hwndTool = GetDlgItem(hDlg, toolID);
    
    // Create the ToolTip.
    HWND hwndTip = CreateWindowEx(NULL, TOOLTIPS_CLASS, NULL,
                              WS_POPUP |TTS_ALWAYSTIP | TTS_BALLOON,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              CW_USEDEFAULT, CW_USEDEFAULT,
                              hDlg, NULL, 
                              g_hInst, NULL);
                              
   if (!hwndTool || !hwndTip)
   {
       return FALSE;
   }                              
                              
    // Associate the ToolTip with the tool.
    TOOLINFO toolInfo = { 0 };
    toolInfo.cbSize = sizeof(toolInfo);
    toolInfo.hwnd = hDlg;
    toolInfo.uFlags = TTF_IDISHWND | TTF_SUBCLASS;
    toolInfo.uId = (UINT_PTR)hwndTool;
    toolInfo.lpszText = pText;
    SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo);

    return TRUE;
}

Creating a ToolTip for a Rectangular Area

The following example demonstrates how to create a standard ToolTip control for a window's entire client area.

void CreateToolTipForRect(HWND hwndParent)
{
    // Create a ToolTip.
    HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST,
        TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,		
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        hwndParent, NULL, g_hInst,NULL);

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

    // Set up "tool" information.
    // In this case, the "tool" is the entire parent window.
    TOOLINFO ti = { 0 };
    ti.cbSize = sizeof(TOOLINFO);
    ti.uFlags = TTF_SUBCLASS;
    ti.hwnd = hwndParent;
    ti.hinst = g_hInst;
    ti.lpszText = TEXT("This is your ToolTip string.");;
    GetClientRect (hwndParent, &ti.rect);

    // Associate the ToolTip with the "tool" window.
    SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);	
} 

The following illustration shows the ToolTip displayed when the mouse pointer is within the client window of a dialog box. The handle of the dialog box was passed to the function shown in the preceding example.

ToolTip for a rectangular area.

Implementing Tracking ToolTips

Tracking ToolTips remain visible until explicitly closed by the application, and can change position on the screen dynamically. They are supported by version 4.70 and later of the common controls.

To create a tracking ToolTip, include the TTF_TRACK flag in the uFlags member of the TOOLINFO structure when sending the TTM_ADDTOOL message.

Your application must manually activate (show) and deactivate (hide) a tracking ToolTip by sending a TTM_TRACKACTIVATE message. 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:

  • By default, the ToolTip is displa;yed next to the corresponding tool in a position the control chooses. The location chosen is relative to the coordinates you provide using this message.
  • If you include the TTF_ABSOLUTE value in the uFlags member of the TOOLINFO structure, the ToolTip is displayed at the pixel location specified in the message. In this case, the control does not attempt to change the ToolTip window's location from the coordinates you provide.

The following example demonstrates how to create a tracking ToolTip control. The example specifies the main window's entire client area as the tool.

The uFlags member of the TOOLINFO structure used in the example includes the TTF_ABSOLUTE flag. Without this flag, the ToolTip control chooses where to display the ToolTip, and its position relative to the dialog box may change suddenly as the mouse pointer moves.

//g_toolItem is a global TOOLITEM structure.

HWND CreateTrackingToolTip(int toolID, HWND hDlg, WCHAR* pText)
{
    // Create a ToolTip.
    HWND hwndTT = CreateWindowEx(WS_EX_TOPMOST,
        TOOLTIPS_CLASS, NULL,
        WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,		
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        hDlg, NULL, g_hInst,NULL);

    if (!hwndTT)
    {   
        return NULL;
    }

    // Set up tool information.
    // In this case, the "tool" is the entire parent window.
    g_toolItem.cbSize = sizeof(TOOLINFO);
    g_toolItem.uFlags = TTF_IDISHWND | TTF_TRACK | TTF_ABSOLUTE;
    g_toolItem.hwnd = hDlg;
    g_toolItem.hinst = g_hInst;
    g_toolItem.lpszText = pText;
    g_toolItem.uId = (UINT_PTR)hDlg;
    GetClientRect (hDlg, &g_toolItem.rect);

    // Associate the ToolTip with the tool window.
    SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &g_toolItem);	
    return hwndTT;
}

The following example code is from the window procedure for a dialog box that displays the tracking ToolTip created in the preceding example. The global Boolean variable g_TrackingMouse is used to determine whether it is necessary to reactivate the ToolTip and reset mouse tracking so that the application is notified when the mouse pointer leaves the client area of the dialog box. When the mouse pointer is within the client area, the ToolTip is active and displays the cursor coordinates, as shown in the illustration.

A tracking ToolTip that shows the cursor coordinates.

//g_hwndTrackingTT is a global HWND variable

case WM_INITDIALOG:
        InitCommonControls();
        g_hwndTrackingTT = CreateTrackingToolTip(IDC_BUTTON1, hDlg, L"");
        return TRUE;

case WM_MOUSELEAVE:
    // The mouse pointer has left our window.
    // Deactivate the ToolTip.
    SendMessage(g_hwndTrackingTT, TTM_TRACKACTIVATE, (WPARAM)FALSE, (LPARAM)&g_toolItem);
    g_TrackingMouse = FALSE;
    return FALSE;

case WM_MOUSEMOVE:
    static int oldX, oldY;
    int newX, newY;

    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);
        g_TrackingMouse = TRUE;
    }

    newX = GET_X_LPARAM(lParam);
    newY = GET_Y_LPARAM(lParam);

    // Make sure the mouse has actually moved. The presence of the ToolTip 
    // causes Windows to send the message continuously.
    if ((newX != oldX) || (newY != oldY))
    {
        oldX = newX;
        oldY = newY;
            
        // Update the text.
        WCHAR coords[12];
        swprintf_s(coords, ARRAYSIZE(coords), L"%d, %d", newX, newY);
        g_toolItem.lpszText = coords;
        SendMessage(g_hwndTrackingTT, TTM_SETTOOLINFO, 0, (LPARAM)&g_toolItem);

        // Position the ToolTip. 
        // The coordinates are adjusted so that the ToolTip does not
        // overlap the mouse pointer.
        POINT pt = { newX, newY }; 
        ClientToScreen(hDlg, &pt);
        SendMessage(g_hwndTrackingTT, TTM_TRACKPOSITION,
            0, (LPARAM)MAKELONG(pt.x + 10, pt.y - 20));
    }
    return FALSE;

Implementing 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 wraps to the next line rather than widening the display region. The rectangle height is increased as needed to accommodate the additional lines. The ToolTip control wraps 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 enables a multiline ToolTip by setting the display rectangle to 150 pixels. A manual line break is inserted after the first word to show that line breaks can be hard as well as soft. The resulting display is shown in the illustration.

A multiline ToolTip.

case WM_NOTIFY:
{
    switch (((LPNMHDR)lParam)->code)
    {
    case TTN_GETDISPINFO:
        LPNMTTDISPINFO pInfo = (LPNMTTDISPINFO)lParam;
        SendMessage(pInfo->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, 150);
        wcscpy_s(pInfo->szText, ARRAYSIZE(pInfo->szText), 
            L"This\nis a very long text string " \
            L"that must be broken into several lines.");
        break;
    }
    break;
}

Implementing 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 in the following illustration. 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.

Default position for a balloon ToolTip

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 points to the center of the lower edge of the tool's rectangle, and the text rectangle is displayed directly below the tool. The stem attaches 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 is centered above the tool, and the stem attaches to the center of the lower edge.

The following illustration shows a ToolTip that is centered on the tool.

A centered balloon ToolTip.

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.

Implementing ToolTips for Status Bar Icons

A nonintrusive way to display an explanatory message for a status bar icon is to implement a ToolTip. The ToolTip disappears when clicked, but you can also specify a time-out value.

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.

#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);

Implementing In-Place ToolTips

In-place ToolTips are used to display text strings for objects that have been clipped. For an illustration, see About ToolTip Controls.

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 rectangle that surrounds the complete label text.
  • The rectangle that surrounds the ToolTip text. The ToolTip text is identical to the complete label text, and normally is the same size and font. The two text rectangles will thus usually be the same size.
  • The ToolTip's window rectangle. This rectangle is somewhat larger than the ToolTip text rectangle that it encloses.

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

Areas to consider when positioning a ToolTip

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

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

Tags What's this?: Add a tag
Community Content   What is Community Content?
Add new content RSS  Annotations
Processing
© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Page view tracker