winapimfccmenu

MFC: How do you add a bitmap to CMenu items added on OnInitMenuPopup?


I need to add custom menu items as needed. I found OnInitMenuPopup (WM_INITMENUPOPUP) does what I need but I can't get an icon to show next to the text on the menu? I've tried a 16x16 png graphic using m_MyGraphic as a CPngImage, I've tried attaching it to a CBitmap, I've tried saving the graphic as a .bmp and loading as CBitmap. I've tried not setting the graphic on the load, but then trying to do it with SetMenuItemBitmaps(), I've tried a 13x13 graphic, I've tried a 15x15 graphic (which matches GetMenuCheckMarkDimensions()). Never does a graphic show next to the menu item? What am I doing wrong or missing?

TIA!

void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu, UINT nIndex, BOOL bSysMenu)
{
  // add items
  if (pPopupMenu && pPopupMenu->GetMenuItemCount() > 0 && pPopupMenu->GetMenuItemID(0) == ID_MY_EXPECTED_ID) {
    // loop though and add menu items
    for (UINT i=0; i<theApp.m_MyList.GetCount(); i++) {
      CString s;
      s.Format(_T("%i: %s"), i, theApp.m_MyList[i].String);
      MENUITEMINFO mii={};
      mii.cbSize=sizeof(mii);
      mii.fMask=MIIM_ID|MIIM_STRING|MIIM_BITMAP;
      mii.wID=ID_MY_RANGE_0+i;
      mii.dwTypeData=s.GetBuffer();
      mii.hbmpItem=(HBITMAP)m_MyBitmap.GetSafeHandle();
      pPopupMenu->InsertMenuItem(i+1, &mii, TRUE);
      // not working above so tried using this as well but it doesn't work either:
      //pPopupMenu->SetMenuItemBitmaps(i+1, MF_BYPOSITION, &m_MyBitmap, &m_MyBitmap);
    }
  }

  CFrameWndEx::OnInitMenuPopup(pPopupMenu, nIndex, bSysMenu);
}

Solution

  • I found a work around. First add CMFCToolBarMenuButton::m_bAlwaysCallOwnerDraw=TRUE; somewhere on initialization.

    Then handle drawing it:

    BOOL CMainFrame::OnDrawMenuImage(CDC* pDC, const CMFCToolBarMenuButton* pMenuButton, const CRect& rectImage)
    {
      BOOL result=FALSE;
      if (pMenuButton->m_nID>=ID_MY_RANGE_0 && pMenuButton->m_nID<=ID_MY_RANGE_N) {
    
        // size to use on menu
        CSize sizemenuimage = CMFCToolBar::GetMenuImageSize();
    
        // get size of our bitmap
        BITMAP bitmap;
        m_MyBitmap.GetBitmap(&bitmap);
    
        // create dc to attach bitmap to
          CDC dcmem;
        if (dcmem.CreateCompatibleDC(pDC)) {
          // attach bitmap to dc
          CBitmap * poldbitmap=dcmem.SelectObject(&m_MyBitmap);
          if (poldbitmap) {
            // Draw bitmap
            result=pDC->StretchBlt(rectImage.left+(rectImage.Width()-sizemenuimage.cx)/2, 
                                   rectImage.top+(rectImage.Height()-sizemenuimage.cy)/2, 
                                   sizemenuimage.cx, sizemenuimage.cy, 
                                   &dcmem, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
            // Select original object
            dcmem.SelectObject(poldbitmap);
          }
          dcmem.DeleteDC();
        }
      }
    
      return result;
    }