【问题标题】:How to add tooltip to menu item如何将工具提示添加到菜单项
【发布时间】:2017-06-03 12:48:14
【问题描述】:

我正在寻找在我的 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 消息,该消息仅在单击菜单时发送,而不是悬停在上方。

我想要的假设图像。

欢迎提出任何建议。

【问题讨论】:

  • 对此不确定,但您是否尝试过任何 WM_MOUSEHOVER、WM_MOUSEMOVE 或 WM_NCMOUSEMOVE 事件,它们是否有效?
  • @Laszlo: WM_NCMOUSEMOVE 是唯一有用的:wParam 总是 5 遍及整个菜单,但 lParam x 和 y 鼠标坐标...我可以用它来识别按钮GetMenuItemRect()!
  • WM_MENUSELECT 每当菜单项被选择时发送,无论是通过滚动/悬停在菜单项上,还是使用键盘。这是处理以显示工具提示的正确消息。它工作正常。如果您在使用时遇到问题,请出示您的实际代码。
  • @Salvador:酷。感谢您的信息。
  • @RemyLebeau:是的,没错,但我认为 Salvador 希望始终显示一个工具提示,只要光标悬停在它上面,而不仅仅是在它被选中时。鼠标移动时是否选择菜单取决于用户设置。

标签: c winapi menu tooltip


【解决方案1】:

终于找到了一个足够好的解决方案,让工具提示在鼠标悬停时出现并在鼠标移出时消失(不完美,因为没有初始或自动弹出延迟时间)。

#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

  • 奇怪的是 TTM_POPUP 没有在 commctrl.h 中由 MinGW (gcc 5.3.0) 定义。
  • TTM_POPUP 需要Visual Styles enabled with manifest
  • 最终对我来说TTM_POPUP 在这种情况下无效

【讨论】:

    【解决方案2】:

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

    #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 上进行了测试:它可以工作,但在 CreateWindow 之后 GetLastError 返回 1309 ERROR_NO_IMPERSONATION_TOKEN
    为了解决这个问题,create a manifest file 并在资源 (.rc) 文件中添加以下行:

    CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "YourApp.exe.manifest"
    

    【讨论】:

      猜你喜欢
      • 2019-08-14
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-06-06
      • 2010-11-12
      • 1970-01-01
      • 2022-01-21
      相关资源
      最近更新 更多