简体   繁体   English

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

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

Using only Win32 C++ (no WTL or MFC or any other third-party library), how can I get custom menu borders?仅使用 Win32 C++(没有 WTL 或 MFC 或任何其他第三方库),如何获得自定义菜单边框?

I was able to ownerdrawn the items but the borders are in the Non Client area and I was unable to find a way change them.我能够拥有这些项目,但边界在非客户区域,我无法找到改变它们的方法。

Is there a way?有办法吗?

No matter how you implement this it is going to be a bit of a hack.无论您如何实现这一点,它都将是一个 hack。

One option is to forget about HMENUs and build your own menus with a custom always on top window.一种选择是忘记 HMENU 并使用自定义始终在顶部窗口构建自己的菜单。 This is probably way too much work and you will never get everything perfect.这可能是太多的工作,你永远不会让一切都完美。 Just off the top of my head you have to deal with LTR vs. RTL, accessibility, configurable settings like the shadow and menu animations (sliding/fading).就在我的脑海中,您必须处理 LTR 与 RTL、可访问性、可配置设置,如阴影和菜单动画(滑动/淡入淡出)。 There are probably things SetMenu does to a HWND that you cannot replicate with a hack like this but you can sidestep that issue by implementing it in a rebar . SetMenu对 HWND 所做的某些事情可能无法通过这样的 hack 复制,但您可以通过在 rebar 中实现它来回避该问题。

If you want to keep using HMENUs then you have to use SetWindowsHookEx to find the menus HWND.如果您想继续使用 HMENU,则必须使用SetWindowsHookEx来查找菜单 HWND。 The menu class is #32768 .菜单类是#32768 You can then subclass the window and override the WM_NC* and WM_PRINT* messages.然后,您可以子类化窗口并覆盖 WM_NC* 和 WM_PRINT* 消息。 This Codeproject article also has information about a undocumented message (0x01e5) you need to handle. 此 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;
}

enter image description here在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM