4

I'm looking for a way to get the tooltip control (if any) which is associated with a given HWND. The text of the tooltip control would be sufficient, too. The closest thing I found is the TTM_GETTEXT message, but it's meant to be sent to the tooltip control itself instead of the tool it's associated with. I don't have a handle to the tooltip control though. Does anybody know how to do this?

All this is done using plain Windows API in C++.

Frerich Raabe
  • 90,689
  • 19
  • 115
  • 207

4 Answers4

2

There doesn't seem to be a specific message to get the tip or its text from the control, but this is how MFC's CWnd class implements OnToolHitTest(), which you should be able to adapt to Win32:

INT_PTR SomeFunction(HWND hWndChild, TOOLINFO *pTI)
{
    if (hWndChild != NULL) // Your HWND being tested
    {
        // return positive hit if control ID isn't -1
        INT_PTR nHit = _AfxGetDlgCtrlID(hWndChild);
        // Replace with GetDlgCtrlID().

        // hits against child windows always center the tip
        if (pTI != NULL && pTI->cbSize >= sizeof(AFX_OLDTOOLINFO))
        {
            // setup the TOOLINFO structure
            pTI->hwnd = m_hWnd;
            pTI->uId = (UINT_PTR)hWndChild;
            pTI->uFlags |= TTF_IDISHWND;
            pTI->lpszText = LPSTR_TEXTCALLBACK;

            // set TTF_NOTBUTTON and TTF_CENTERTIP if it isn't a button
            if (!(::SendMessage(hWndChild, WM_GETDLGCODE, 0, 0) & DLGC_BUTTON))
                pTI->uFlags |= TTF_NOTBUTTON|TTF_CENTERTIP;
        }
        return nHit;
    }
    return -1;  // not found
}

Hopefully this will be useful.

Michael Myers
  • 188,989
  • 46
  • 291
  • 292
JTeagle
  • 2,196
  • 14
  • 15
1

To get tooltip text from some control you could use TTN_NEEDTEXT message. It was designed to be used by the ToolTip control, but I cannot see any reason why you could not send it from other place.

Kirill V. Lyadvinsky
  • 97,037
  • 24
  • 136
  • 212
  • 2
    Looks interesting - unfortunately it's only sent by the tooltip if the tooltip's TOOLINFO::lpszText field was set to LPSTR_TEXTCALLBACK. So each time the tooltip is displayed, it will ask the control for the text to show. Maybe this is the common case (I hope so), but I suspect that there are still plenty of tooltips out there which have a static text (i.e. TOOLINFO::lpszText is set to a static string). – Frerich Raabe Aug 26 '09 at 14:38
1

You could enumerate the windows looking for a tooltip control that has a parent of the required window. You'll need to supply the window together with the tool id (normally from GetDlgCtrlID)...:

HWND hToolTipWnd = NULL;

BOOL GetToolTipText(HWND hWnd, UINT nId, std::wstring& strTooltip)
{
    hToolTipWnd = NULL;
    EnumWindows(FindToolTip, (LPARAM)hWnd);

    if (hToolTipWnd == NULL)
        return FALSE;

    WCHAR szToolText[256];
    TOOLINFO ti;
    ti.cbSize = sizeof(ti);
    ti.hwnd = hWnd;
    ti.uId = nId;
    ti.lpszText = szToolText;

    SendMessage(hToolTipWnd, TTM_GETTEXT, 256, (LPARAM)&ti);
    strTooltip = szToolText;

    return TRUE;
}

BOOL CALLBACK FindToolTip(HWND hWnd, LPARAM lParam)
{
    WCHAR szClassName[256];
    if (GetClassName(hWnd, szClassName, 256) == 0)
        return TRUE;

    if (wcscmp(szClassName, L"tooltips_class32") != 0)
        return TRUE;
    if (GetParent(hWnd) != (HWND)lParam)
        return TRUE;

    hToolTipWnd = hWnd;

    return FALSE;
}
Alan
  • 13,510
  • 9
  • 44
  • 50
  • 1
    Unfortunately, this seems to require that the tooltip is visible. Otherwise, there is no tooltip window handle which the `FindToolTip` function could notice. – Frerich Raabe Jul 21 '10 at 10:50
1

I don't know if the window whose tooltip you want to retrieve is a child of a window you have created.

If this is the case, you can handle the NM_TOOLTIPSCREATED notification, which is sent by a child window to its parent when it creates a tooltip (or should be sent: it is true for common controls but I don't know for other kinds of windows). This notification includes a handle to the tooltip window.

Yoon5oo
  • 496
  • 5
  • 11
Adrien Plisson
  • 22,486
  • 6
  • 42
  • 73