MFC:如何将位图添加到在 OnInitMenuPopup 上添加的 CMenu 项?
MFC: How do you add a bitmap to CMenu items added on OnInitMenuPopup?
我需要根据需要添加自定义菜单项。我发现 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, 0, 0, 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(), 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);
}
我需要根据需要添加自定义菜单项。我发现 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, 0, 0, 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(), 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);
}