Simple way to put bitmaps to menu.
Or is there simpler way to do that ?
...
hBitmap = LoadBitmap(GetModuleHandle(TEXT("comctl32")), MAKEINTRESOURCE(120));
...
hBMNew = GetBitmapByPos(hBitmap, 6);
...
SetMenuItemBitmaps(hMenuT, IDM_NEW, MF_BYCOMMAND, hBMNew, hBMNew);
...
HBITMAP GetBitmapByPos(HBITMAP hBMSrc, int nPos)
{
HDC hDCSrc, hDCDst;
BITMAP bm;
HBITMAP hBMDst = NULL;
if ((hDCSrc = CreateCompatibleDC(NULL)) != NULL) {
if ((hDCDst = CreateCompatibleDC(NULL)) != NULL) {
SelectObject(hDCSrc, hBMSrc);
GetObject(hBMSrc, sizeof(bm), &bm);
hBMDst = CreateBitmap(bm.bmHeight, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel, NULL);
if (hBMDst) {
GetObject(hBMDst, sizeof(bm), &bm);
HBITMAP hOldBmp = SelectObject(hDCDst, hBMDst);
BitBlt(hDCDst, 0, 0, bm.bmHeight, bm.bmHeight, hDCSrc, nPos*bm.bmHeight, 0, SRCCOPY);
SelectObject(hDCDst, hOldBmp);
}
DeleteDC(hDCDst);
}
DeleteDC(hDCSrc);
}
return hBMDst;
}
This version shows whole picture:
HBITMAP GetBitmapByPos4Menu(HBITMAP hBMSrc, int nPos)
{
HDC hDCSrc, hDCDst;
BITMAP bm;
HBITMAP hBMDst = NULL;
int cx, cy;
cx = GetSystemMetrics(SM_CXMENUCHECK);
cy = GetSystemMetrics(SM_CYMENUCHECK);
if ((hDCSrc = CreateCompatibleDC(NULL)) != NULL) {
if ((hDCDst = CreateCompatibleDC(NULL)) != NULL) {
SelectObject(hDCSrc, hBMSrc);
GetObject(hBMSrc, sizeof(bm), &bm);
hBMDst = CreateBitmap(cx, cy, bm.bmPlanes, bm.bmBitsPixel, NULL);
if (hBMDst) {
HBITMAP hOldBmp = SelectObject(hDCDst, hBMDst);
StretchBlt(hDCDst, 0, 0, cx, cy, hDCSrc, nPos*bm.bmHeight, 0, bm.bmHeight, bm.bmHeight, SRCCOPY);
SelectObject(hDCDst, hOldBmp);
GetObject(hBMDst, sizeof(bm), &bm);
}
DeleteDC(hDCDst);
}
DeleteDC(hDCSrc);
}
return hBMDst;
}
EDIT:
This function creates bitmap with selected background color:
(Example in WSDIFrameMenuBM.zip uses it)
HBITMAP CreateBitmapMasked(HBITMAP hBMSrc, COLORREF crTransparent, COLORREF crBackground)
{
HDC hDCMem, hDCMem2, hDCDst1;
BITMAP bm;
HBITMAP hBMDst1 = NULL;
HBITMAP hBMDst2 = NULL;
HBITMAP hBMMask = NULL;
GetObject(hBMSrc, sizeof(bm), &bm);
hDCMem = CreateCompatibleDC(NULL);
hDCMem2 = CreateCompatibleDC(NULL);
hBMDst1 = CreateBitmap(bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel, NULL); // new bitmap
hBMDst2 = CreateBitmap(bm.bmWidth, bm.bmHeight, bm.bmPlanes, bm.bmBitsPixel, NULL); // copy bitmap
hBMMask = CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL); // mask bitmap
// make copy of source bitmap
SelectObject(hDCMem, hBMSrc); // source
SelectObject(hDCMem2, hBMDst2); // target
BitBlt(hDCMem2, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCCOPY); //
DeleteDC(hDCMem); // free source
DeleteDC(hDCMem2);
// make masks
hDCMem = CreateCompatibleDC(NULL);
hDCMem2 = CreateCompatibleDC(NULL);
SelectObject(hDCMem, hBMDst2);
SelectObject(hDCMem2, hBMMask);
SetBkColor(hDCMem, crTransparent);
BitBlt(hDCMem2, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCCOPY);
BitBlt(hDCMem, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem2, 0, 0, SRCINVERT);
DeleteDC(hDCMem);
DeleteDC(hDCMem2);
RECT rc;
rc.top = rc.left = 0;
rc.right = bm.bmWidth;
rc.bottom = bm.bmHeight;
hDCMem = CreateCompatibleDC(NULL);
hDCDst1 = CreateCompatibleDC(NULL);
SelectObject(hDCDst1, hBMDst1);
FillRect(hDCDst1, &rc, (HBRUSH)crBackground);
SelectObject(hDCMem, hBMMask);
BitBlt(hDCDst1, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCAND);
SelectObject(hDCMem, hBMDst2);
BitBlt(hDCDst1, 0, 0, bm.bmWidth, bm.bmHeight, hDCMem, 0, 0, SRCPAINT);
DeleteDC(hDCMem);
DeleteDC(hDCDst1);
DeleteObject(hBMDst2);
DeleteObject(hBMMask);
return hBMDst1;
}
EDIT 20221014: fixed GetBitmapByPos4Menu()
Even simpler way with comctl32:
EDIT 20140114: WSDIMenuBM_OD1_2.zip with ownerdraw and ImageList
In WM_CREATE...
himl = ImageList_LoadBitmap(GetModuleHandle(TEXT("comctl32")), MAKEINTRESOURCE(120), 16, 15, RGB(192,192,192));
InitMenuBitmaps(hwnd);
...
void InitMenuBitmaps(HWND hwnd)
{
MENUITEMINFO mii;
HMENU hMenu;
hMenu = GetSubMenu(GetMenu(hwnd), 0);
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_BITMAP | MIIM_DATA;
mii.hbmpItem = HBMMENU_CALLBACK;
mii.dwItemData = 6;
SetMenuItemInfo(hMenu, IDM_NEW, FALSE, &mii);
...
}
case WM_DRAWITEM:
return OnDrawItem(hwnd,(const DRAWITEMSTRUCT*)lParam),0;
void OnDrawItem(HWND hwnd, const DRAWITEMSTRUCT * lpDrawItem)
{
if (lpDrawItem->CtlType == ODT_MENU) {
if (lpDrawItem->itemData) {
ImageList_Draw(himl, lpDrawItem->itemData, lpDrawItem->hDC, 2, 2, ILD_NORMAL );
}
}
return;
}