如何将工具提示添加到菜单项

时间:2017-01-18 23:31:15

标签: c winapi menu tooltip

我正在寻找一个解决方案来显示我的WinAPI程序中单个菜单项的工具提示。

ID_MAIN_MENU MENU
    BEGIN
        ...
    END
    MENUITEM "?", ID_RIGHT_BUTTON, HELP
END

我可以使用TOOLINFO结构和TTM_ADDTOOL消息add tooltip for a control,但这似乎不适用于HMENU句柄。

我发现some C++ libraries向菜单项添加了工具提示,但我使用了C.
此外,它无法使用WM_MENUSELECT消息,该消息仅在点击菜单时发送,而不是悬停在上面。

Tooltip on single menu item我想要的假想图像。

任何建议都表示赞赏。

2 个答案:

答案 0 :(得分:0)

最后找到一个足够好的解决方案,使鼠标悬停在工具提示上,并在鼠标输出时消失(不完美,因为没有初始或自动延迟时间)。

#define _WIN32_IE 0x0300    // to reach TTM_TRACKACTIVATE in <commctrl.h>
#include <windows.h>
#include <commctrl.h>

HWND hToolTip;
TOOLINFO ti = {0}; 

// WndProc
    case WM_CREATE: {
        HMENU hmenu = CreateMenu();
        AppendMenu( hmenu, MF_HELP, 123, "?" );
        SetMenu( hWnd, hmenu );

        hToolTip = CreateWindow( TOOLTIPS_CLASS, 0, WS_POPUP, CW_USEDEFAULT, CW_USEDEFAULT,
                                 CW_USEDEFAULT, CW_USEDEFAULT, hWnd, 0, 0, 0);
        ti.cbSize = sizeof(TOOLINFO);
        ti.hwnd = hWnd;
        ti.uId = (UINT)hToolTip;
        ti.lpszText = "My tooltip";
        SendMessage( hToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti );
        break;
    }
    case WM_NCMOUSEMOVE: {
        RECT rect;
        GetMenuItemRect( hWnd, GetMenu(hWnd), 0, &rect );
                                           // ^ zero-based position of the menu item
        int x = LOWORD(lParam);
        int y = HIWORD(lParam);
        if ( x>=rect.left && y>=rect.top && x<rect.right && y<rect.bottom )
            SendMessage( hToolTip, TTM_TRACKACTIVATE, TRUE, (LPARAM)&ti );
        else
            SendMessage( hToolTip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&ti );
        break;
    }
    case WM_MOUSEMOVE:
        SendMessage( hToolTip, TTM_TRACKACTIVATE, FALSE, (LPARAM)&ti );
        break;

为什么我使用TTM_TRACKACTIVATE代替TTM_POPUP

答案 1 :(得分:0)

我提出了一种更简单,更有效的解决方案,为单个菜单项创建工具提示:

#include <windows.h>
#include <commctrl.h>

#define ID_BUTTON 123
HWND hToolTip;
TOOLINFO ti = {0};

// WndProc
    case WM_CREATE: {
        // create menu
        HMENU hmenu = CreateMenu();
        AppendMenu( hmenu, MF_HELP, ID_BUTTON, "?" );
        SetMenu( hWnd, hmenu );

        InitCommonControls();   // necessary in Windows XP to register TOOLTIPS_CLASS

        // create tooltip
        hToolTip = CreateWindow( TOOLTIPS_CLASS, 0, WS_POPUP, 0, 0, 0, 0, hWnd, 0, 0, 0 );
        ti.cbSize = sizeof(TOOLINFO);
        ti.uFlags = TTF_SUBCLASS;
        ti.hwnd = hWnd; // main window handle
        ti.uId = (UINT)ID_BUTTON;   // distinguish it from eventual other tooltips
        ti.lpszText = "My tooltip";
        SendMessage(hToolTip, TTM_ADDTOOL, 0, (LPARAM)&ti);
        break;
    }
    case WM_SIZE:
        ti.uId = (UINT)ID_BUTTON;
        // get new coordinates of item
        GetMenuItemRect( hWnd, GetMenu(hWnd), 0, &ti.rect );
                                           // ^ zero-based position of the menu item
        // convert from screen to client coordinates
        MapWindowPoints( NULL, hWnd, (LPPOINT)&ti.rect, 2 );
                      // ^ desktop handle               ^ POINT structures that is one RECT
        SendMessage(hToolTip, TTM_NEWTOOLRECT, 0, (LPARAM)&ti);
        break;

我使用InitCommonControls因为它更短且有效,但也已过时,应使用InitCommonControlsEx

以上代码也在Windows XP上进行了测试:它可以正常运行,但GetLastError CreateWindow后返回1309 ERROR_NO_IMPERSONATION_TOKEN。 为了解决它,create a manifest file和资源(.rc)文件中添加以下行:

CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"