纯 Win32 C++(无 WTL、MFC 等)中的自定义菜单边框

Custom menu border in pure Win32 C++ (w/o WTL, MFC, etc)

本文关键字:自定义 边框 菜单 MFC C++ Win32 WTL      更新时间:2023-10-16

仅使用 Win32 C++(没有 WTL 或 MFC 或任何其他第三方库),如何获取自定义菜单边框?

能够所有者绘制项目,但边框位于非客户区域,我无法找到更改它们的方法。

有办法吗?

无论你如何实现这一点,这都会是一个黑客。

一种选择是忘记 HMENU,并使用自定义的始终在顶部窗口构建自己的菜单。这可能是太多的工作,你永远不会得到一切完美。在我的头顶上,你必须处理LTR与RTL,可访问性,可配置的设置,如阴影和菜单动画(滑动/淡入淡出)。SetMenu可能对 HWND 所做的一些事情您无法通过这样的黑客复制,但您可以通过在钢筋中实现它来回避这个问题。

如果你想继续使用HMENUs,那么你必须使用SetWindowsHookEx来查找菜单HWND。菜单类是 #32768 。然后,您可以对窗口进行子类化并覆盖 WM_NC* 和 WM_PRINT* 消息。这篇 Codeproject 文章还包含有关需要处理的未记录消息 (0x01e5) 的信息。

static bool isInitPopup = false;
switch (message)
{
case WM_INITMENUPOPUP:
{
    isInitPopup = true;
    break;
}
case WM_DRAWITEM:
{
    LPDRAWITEMSTRUCT lpDIS = (LPDRAWITEMSTRUCT)lParam;
    if (lpDIS->CtlType == ODT_MENU)
    {
        auto hMenuWnd = FindWindow(_T("#32768"), NULL);
        if (IsWindow(hMenuWnd)&& isInitPopup)
        {
            RECT rect;
            ::GetWindowRect(hMenuWnd, &rect);
            auto menuDc = ::GetWindowDC(hMenuWnd);
            ::OffsetRect(&rect, -rect.left, -rect.top);
            int border = 1;
            rect.left = rect.left + border;
            rect.top = rect.top + border;
            rect.bottom = rect.bottom - border;
            rect.right = rect.right - border;
            HBRUSH bg = CreateSolidBrush(RGB(255,0,0));
            //Rectangle(menuDc, rect.left, rect.top, rect.right, rect.bottom);
            int borderThiness = 3;
            ::ExcludeClipRect(menuDc, rect.left+ borderThiness, rect.top+ borderThiness, rect.right- borderThiness, rect.bottom- borderThiness);
            ::FillRect(menuDc, &rect, bg);
            DeleteObject(bg);
            isInitPopup = false;
        }
    break;
}

在此处输入图像描述