【问题标题】:MFC: How do you add a bitmap to CMenu items added on OnInitMenuPopup?MFC:如何为 OnInitMenuPopup 上添加的 CMenu 项目添加位图?
【发布时间】:2020-09-08 22:02:09
【问题描述】:

我需要根据需要添加自定义菜单项。我发现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);
}

【问题讨论】:

  • 应该可以。你如何加载你的m_MyBitmap位图,你能显示你的代码吗?
  • 您正在尝试修改您的应用程序创建/维护的菜单?还是您要修改系统提供的系统菜单?
  • 你通常不需要做这一切,如果你添加一个 TOOLBAR 资源并分配与菜单中相同的 ID,MFC 将在你的菜单项中显示位图(你不需要创建或显示工具栏)。图标默认为 16×15 像素大,因此对于 4 个项目,您需要一个 60×15 像素大的位图。
  • 是的,为此我有一个CMFCDropDownToolbar,我使用工具栏加载的共享图标添加项目。它的图标在那里,菜单不会选择。我必须自己做,我找到了解决方法,请参阅答案。
  • 我只使用CPngImage m_MyBitmap' m_MyBitmap.Load(ID)` 加载位图 - 尝试使用 CBitmap 获取 .bmp 等时也是如此。从未工作过(并查看 @987654332 的 MFC 代码@,它似乎覆盖了解释为什么它不起作用的位图)。

标签: winapi mfc cmenu


【解决方案1】:

我找到了解决办法。首先在初始化的某处添加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, 0, 0, bitmap.bmWidth, bitmap.bmHeight, SRCCOPY);
        // Select original object
        dcmem.SelectObject(poldbitmap);
      }
      dcmem.DeleteDC();
    }
  }

  return result;
}

【讨论】:

  • 我要等两天。
  • @zhu 不要要求人们接受最坏的解决方案。这是菜单实现支持的东西。
【解决方案2】:

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

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(), 0, 0, hIcon, 13, 13, 0, (HBRUSH)RGB(255, 255, 255), DI_NORMAL);
    dc.SelectObject(pOldBmp);
    dc.DeleteDC();
    HBITMAP hBitmap = (HBITMAP)::CopyImage((HANDLE)((HBITMAP)bmp), 
            IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE);

    return CBitmap::FromHandle(hBitmap);
}

【讨论】:

  • 不起作用,已经尝试过,如问题所示。可能与使用CMFCMenuBar 有关
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-04
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-10
相关资源
最近更新 更多