6

Using only Win32 C++ (no WTL or MFC or any other third-party library), how can I get custom menu borders?

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?

John Hascall
  • 9,176
  • 6
  • 48
  • 72
AP.
  • 5,205
  • 7
  • 50
  • 94
  • 1
    Well, you can always override WM_NCPAINT or create a frame-less window though perhaps you could describe what you are attempting to achieve in more detail? – doynax Dec 27 '13 at 19:42
  • menu s created with CreatePopup/TrackPopupMenu, I do not know how to modify it. – AP. Dec 27 '13 at 19:45
  • 2
    Using an [Owner-Drawn Menu](http://msdn.microsoft.com/en-us/library/windows/desktop/ms647558.aspx#_win32_Creating_Owner_Drawn_Menu_Items) you can customize the appearance of items. Owner-drawn borders are not supported by the system. You would have to create your own window and re-implement the entire menu logic. As an aside: Neither MFC nor WTL allow you to owner-draw the border of a menu. – IInspectable Dec 27 '13 at 22:55
  • You are confirming my fear.. – AP. Dec 28 '13 at 12:40

2 Answers2

4

No matter how you implement this it is going to be a bit of a hack.

One option is to forget about HMENUs and build your own menus with a custom always on top window. 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). 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.

If you want to keep using HMENUs then you have to use SetWindowsHookEx to find the menus HWND. The menu class is #32768. You can then subclass the window and override the WM_NC* and WM_PRINT* messages. This Codeproject article also has information about a undocumented message (0x01e5) you need to handle.

Anders
  • 97,548
  • 12
  • 110
  • 164
0
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