Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
250 views
in Technique[技术] by (71.8m points)

c++ - Unable To Change Menu Bitmap

I have a custom-drawn skin for an app, that eliminates the caption/title bar. All of the menu items and system buttons are owner-drawn. Everything works as it should, except one little bug.

When the Maximize button is pressed, and the window maximizes, the code should also change the button bitmap, from the "Maximize" icon, to the "Restore" icon. Yet, I cannot get it to change. Here is the code that handles that button command:

case ID_MENUBAR_MAX: {
                    WINDOWPLACEMENT wp;
                    wp.length = sizeof(WINDOWPLACEMENT);
                    GetWindowPlacement(hwnd, &wp);
                    mII.cbSize = sizeof(MENUITEMINFO);
                    mII.fMask = MIIM_BITMAP;
                    GetMenuItemInfo(hMenu, NUMMI+2, TRUE, &mII);
                    if (wp.showCmd == SW_SHOWNORMAL){    mII.hbmpItem = hMBB.restore;  SendMessage(hwnd, WM_SYSCOMMAND, SC_MAXIMIZE, 0); }
                    if (wp.showCmd == SW_SHOWMAXIMIZED){ mII.hbmpItem = hMBB.max;      SendMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0);  }
                    SetMenuItemInfo(hMenu, NUMMI+2, TRUE, &mII);
                    DrawMenuBar(hwnd);
                    return 0;
                 }

As I mentioned, everything works as it should. When the button is pressed the window maximizes or normalizes, as it should. I just can't get the bitmap on the button to change along with it. What am I missing? It must be something simple.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It seems that you want to change the bitmap of a button instead of a menu item. You should first specify BS_BITMAP(or BS_ICON) when creating the button, and then send the bitmap to the button handle through the BM_SETIMAGE message, like:

        case ID_MENUBAR_MAX: 
        {
            WINDOWPLACEMENT wp;
            wp.length = sizeof(WINDOWPLACEMENT);
            HWND hMaxButton = (HWND)lParam;
            if (wp.showCmd == SW_SHOWNORMAL) 
            {
                SendMessage(hMaxButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hMBB.restore); 
            }
            if (wp.showCmd == SW_SHOWMAXIMIZED) 
            { 
                SendMessage(hMaxButton, BM_SETIMAGE, IMAGE_BITMAP, (LPARAM)hMBB.max); 
            }

            //DrawMenuBar(hwnd);
            return 0;
        }

EDIT:

I have create an owner-draw menu:

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
    case WM_RBUTTONDOWN:
        OnRightClick(hWnd);
        return TRUE;
    case WM_MEASUREITEM:
        OnMeasureItem(hWnd, (LPMEASUREITEMSTRUCT)lParam);
        return TRUE;
    case WM_DRAWITEM:
        OnDrawItem(hWnd, (LPDRAWITEMSTRUCT)lParam);
        return TRUE;
    ....
    }
}
BOOL WINAPI OnRightClick(HWND hwnd)
{
    HMENU hmenuPopup = CreatePopupMenu();
    MENUITEMINFO mii = { 0 };

    // Add the bitmap menu items to the menu. 
    MYITEM* pMyItem = (MYITEM*)malloc(sizeof(MYITEM));
    //hBitmap1&hBitmap2 have been initialized before
    pMyItem->hBitmap1 = hBitmap1;
    pMyItem->hBitmap2 = hBitmap2;

    mii.cbSize = sizeof(MENUITEMINFO);
    mii.fMask = MIIM_FTYPE | MIIM_DATA;
    mii.fType = MFT_OWNERDRAW;
    mii.dwItemData = (ULONG_PTR)pMyItem;
    InsertMenuItem(hmenuPopup, 0, false, &mii);
    
    RECT rc;
    GetWindowRect(hwnd,&rc);
    TrackPopupMenuEx(hmenuPopup,0,rc.left + 100,rc.top + 100,hwnd,0);

    free(pMyItem);

    return TRUE;
}

VOID WINAPI OnMeasureItem(HWND hwnd, LPMEASUREITEMSTRUCT lpmis)
{
    //lpmis->CtlType = ODT_MENU;
    lpmis->itemWidth = 40;
    lpmis->itemHeight = 40;
}
VOID WINAPI OnDrawItem(HWND hwnd, LPDRAWITEMSTRUCT lpdis)
{
    MYITEM* pMyItem = (MYITEM*)lpdis->itemData;
    HBITMAP hBitmap;
    static int flag = 0;

    if (lpdis->itemState & ODS_SELECTED)
    {
        flag = !flag;
    }
    if(flag)
        hBitmap = pMyItem->hBitmap1;
    else 
        hBitmap = pMyItem->hBitmap2;

    HDC hdcMem = CreateCompatibleDC(lpdis->hDC);
    HBITMAP oldBitmap = (HBITMAP)SelectObject(hdcMem, hBitmap);
    BITMAP bitmap;
    GetObject(hBitmap, sizeof(bitmap), &bitmap);
    BitBlt(lpdis->hDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hdcMem, 0, 0, SRCCOPY);

    SelectObject(hdcMem, oldBitmap);
    DeleteDC(hdcMem);
}

When the mouse selects the menu, the bitmap of the menu will change.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...