MFC:如何将位图添加到OnInitMenuPopup上添加的CMenu项?

问题描述

我需要根据需要添加自定义菜单项。我发现OnInitMenuPopup(WM_INITMENUPOPUP)可以满足我的需求,但是我无法在菜单文本旁边显示图标吗?我尝试使用m_MyGraphic作为CPngImage来制作16x16 png图形,尝试将其附加到CBitmap,尝试将图形另存为.bmp并加载为CBitmap。我尝试过不在负载上设置图形,但是尝试使用SetMenuItemBitmaps()进行设置,尝试了13x13的图形,尝试了15x15的图形(与GetMenuCheckMarkDimensions()匹配)。菜单项旁边永远不会显示图形吗?我在做什么错还是想念?

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);
}

解决方法

我找到了解决方法。首先在初始化的某处添加CMFCToolBarMenuButton::m_bAlwaysCallOwnerDraw=TRUE;

然后处理它:

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,bitmap.bmWidth,bitmap.bmHeight,SRCCOPY);
        // Select original object
        dcmem.SelectObject(poldbitmap);
      }
      dcmem.DeleteDC();
    }
  }

  return result;
}
,

另一个可能的解决方案(如果您已经有了工具栏的位图):

void CMainFrame::OnInitMenuPopup(CMenu* pPopupMenu,UINT nIndex,BOOL bSysMenu) 
{
    CMDIFrameWnd::OnInitMenuPopup(pPopupMenu,nIndex,bSysMenu);

    // TODO: Add your message handler code here

    HICON hIcon = AfxGetApp()->LoadIcon(IDR_TESTMETYPE);
    pPopupMenu->SetMenuItemBitmaps(ID_FILE_NEW,MF_BYCOMMAND,ConvertIconToBitmap(hIcon),NULL);
    ...
    ...
}

其中 SetMenuItemBitmaps 定义为:

CBitmap* CMainFrame::ConvertIconToBitmap(HICON hIcon)
{
    CDC dc;
    CBitmap bmp;
    CClientDC ClientDC(this);
    dc.CreateCompatibleDC(&ClientDC);
    bmp.CreateCompatibleBitmap(&ClientDC,13,13);
    CBitmap* pOldBmp = (CBitmap*)dc.SelectObject(&bmp);
    ::DrawIconEx(dc.GetSafeHdc(),hIcon,(HBRUSH)RGB(255,255,255),DI_NORMAL);
    dc.SelectObject(pOldBmp);
    dc.DeleteDC();
    HBITMAP hBitmap = (HBITMAP)::CopyImage((HANDLE)((HBITMAP)bmp),IMAGE_BITMAP,LR_DEFAULTSIZE);

    return CBitmap::FromHandle(hBitmap);
}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...