我正在尝试将位图添加到弹出菜单。
我遇到的问题是我从 ICON 动态创建位图,并且我遇到了 24 位颜色图标与 24+alpha(32 位)颜色图标的问题。
位图似乎只有在 32bpp(包括 alpha 通道)时才能正确绘制。
这是我的(测试)代码:
void ConvertIconToBitmap(CBitmap& bmpObj, HICON hIcon, int cx, int cy, BOOL useDIB) {
CClientDC screenDC(NULL);
CBitmap bmpTmp;
HANDLE_API_FAILURE( bmpTmp.CreateCompatibleBitmap(&screenDC, cx, cy) );
CDC memDC;
HANDLE_API_FAILURE( memDC.CreateCompatibleDC(&screenDC) );
CBitmap* pOldBmp = memDC.SelectObject(&bmpTmp);
HANDLE_API_FAILURE( ::DrawIconEx( memDC.GetSafeHdc(), 0, 0, hIcon, cx, cy, 0, NULL, DI_NORMAL) );
memDC.SelectObject( pOldBmp );
HBITMAP hDibBmp = (HBITMAP)::CopyImage((HANDLE)(HBITMAP)bmpTmp, IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION);
HANDLE_API_FAILURE( hDibBmp );
if (useDIB) {
HANDLE_API_FAILURE( bmpObj.Attach(hDibBmp) ); // works for 32bit/transparanecy
} else {
HANDLE_API_FAILURE( bmpObj.Attach(bmpTmp.Detach()) ); // works for 24bit
}
}
...
CMenu menu;
menu.LoadMenu(IDR_POPUPMENU);
CMenu* pMenu = menu.GetSubMenu(0);
int cx, cy;
cx = cy = GetSystemMetrics(SM_CYMENU);
MENUITEMINFO mii;
mii.cbSize = sizeof mii;
mii.fMask = MIIM_BITMAP;
HICON pwdIco = ExtractIcon(NULL/*=current instance*/, L"path/to/file.exe", 0);
// If icon is 32bit-alpha this works, but doesn't work with 24bit icon
CBitmap bmpTop;
ConvertIconToBitmap(bmpTop, pwdIco, cx, cy, TRUE);
mii.hbmpItem = bmpTop;
pMenu->SetMenuItemInfo(ID_MENU_TOP, &mii, FALSE);
// If icon is 32bit-alpha transparent areas are shown in black, but 24bit icon is also displayed correctly
CBitmap bmpApp;
ConvertIconToBitmap(bmpApp, pwdIco, cx, cy, FALSE);
HBITMAP bmpTransp = bmpApp;
mii.hbmpItem = bmpTransp;
pMenu->SetMenuItemInfo(ID_MENU_TEST, &mii, FALSE);
this->ClientToScreen(&point);
pMenu->TrackPopupMenu(nFlags, point.x, point.y, this);
因为我需要从现有文件的图标中动态填充菜单条目图像,所以我不能只是静态地整理出位图并使用这些而不是图标。
传递给SetMenuItemInfo的MENUITEMINFO结构HBITMAP
的hbmpItem
成员有什么要求???
以及如何确保“创建”的位图DrawIconEx
满足这些要求?
哦,令我非常高兴的是,我刚刚了解到 32 位 alpha 混合菜单项位图在 Windows XP 下不起作用(那里是透明的=黑色),所以我必须以某种方式自己映射透明度。(可能通过用 替换一些颜色GetSysColor(COLOR_MENU)
。)