c++winapimenudrawingownerdrawn

C++ Win32 Menubar being drawn over owner-drawn menu items


I have 2 owner-drawn menu items, when I launch the program I only see one of the owner-drawn menu items; the first one. It is being drawn except the menubar is drawn over every other menu item which is not drawn in the first position, If I mouse over the second owner-drawn menu item or update it in any other way it draws, If I then interact with the main window (i.g Resizing) in effect updating the menu bar it proceeds to draw over any other owner-drawn item that is not drawn in the first position.

Question: How do I get the menubar to not drawn over menu items,

// Measure Item:

VOID MeasureMenuItem(LPMEASUREITEMSTRUCT ItemStruct)
{
    ItemStruct->itemWidth = 50;
    ItemStruct->itemHeight = 10;
    return;
}

// Draw Item:

VOID DrawMenuItem(LPDRAWITEMSTRUCT ItemStruct)
{
    HDC hDC = ItemStruct->hDC;

    SelectObject(hDC, GetStockObject(DC_PEN));
    SelectObject(hDC, GetStockObject(DC_BRUSH));
    SetBkMode(hDC, TRANSPARENT);
    if (ItemStruct->itemState & ODS_HOTLIGHT)
    {
        SetDCPenColor(hDC, RGB(20, 20, 20));
        SetDCBrushColor(hDC, RGB(20, 20, 20));
        SetTextColor(hDC, RGB(255, 255, 255));
    }
    else
    {
        SetDCPenColor(hDC, RGB(70, 70, 70));
        SetDCBrushColor(hDC, RGB(70, 70, 70));
        SetTextColor(hDC, RGB(255, 255, 255));
    }
    Rectangle(hDC, ItemStruct->rcItem.left, ItemStruct->rcItem.top, ItemStruct->rcItem.right, ItemStruct->rcItem.bottom);

    DrawText(hDC, (LPCWSTR)ItemStruct->itemData, -1, &ItemStruct->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    ReleaseDC(MainWindow, hDC);
    return;
}

// Menus

    HMENU Bar = CreateMenu();
    HMENU File = CreateMenu();
    HMENU Edit = CreateMenu();
    AppendMenu(Bar, MF_OWNERDRAW, (UINT_PTR)File, L"File");
    AppendMenu(Bar, MF_OWNERDRAW, (UINT_PTR)Edit, L"Edit");
    MENUINFO Info;
    Info.cbSize = sizeof(Info);
    Info.fMask = MIM_BACKGROUND;
    Info.hbrBack = (HBRUSH)CreateSolidBrush(RGB(100, 100, 100));
    SetMenuInfo(Bar, &Info);
    SetMenu(MainWindow, Bar);

enter image description hereenter image description here


Solution

  • Why is DrawMenuItem() calling ReleaseDC(MainWindow, hDC);? That doesn't belong there, get rid of it. You didn't obtain the HDC from Get(Window)DC() so you don't own it and shouldn't be trying to release it.

    Also, you are not un-selecting the objects you selected into the HDC. You need to restore the original objects you replaced.

    Try this instead:

    VOID DrawMenuItem(LPDRAWITEMSTRUCT ItemStruct)
    {
        HDC hDC = ItemStruct->hDC;
    
        HPEN oldPen = (HPEN) SelectObject(hDC, GetStockObject(DC_PEN));
        HBRUSH oldBrush = (HBRUSH) SelectObject(hDC, GetStockObject(DC_BRUSH));
        SetBkMode(hDC, TRANSPARENT);
    
        if (ItemStruct->itemState & ODS_HOTLIGHT)
        {
            SetDCPenColor(hDC, RGB(20, 20, 20));
            SetDCBrushColor(hDC, RGB(20, 20, 20));
            SetTextColor(hDC, RGB(255, 255, 255));
        }
        else
        {
            SetDCPenColor(hDC, RGB(70, 70, 70));
            SetDCBrushColor(hDC, RGB(70, 70, 70));
            SetTextColor(hDC, RGB(255, 255, 255));
        }
    
        Rectangle(hDC, ItemStruct->rcItem.left, ItemStruct->rcItem.top, ItemStruct->rcItem.right, ItemStruct->rcItem.bottom);
    
        DrawText(hDC, (LPCWSTR)ItemStruct->itemData, -1, &ItemStruct->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
    
        SelectObject(hDC, oldPen);
        SelectObject(hDC, oldBrush); 
    }