System context menu Icon not transparent like WinRAR
I added a icon at the system context menu(the popped up menu when we right mouse click on any file/foler). But the icon is not transparent(in xp its not notice able, but in vista/win7 it is clearly visible) there is a white background beneath the icon. But WinRAR or TortoiseSVN icons don't have any white background, they are transparent.
I tried the following C++ code:
#define BITMAP_MAIN 201 //in resource.h
BITMAP_M开发者_如何学CAIN BITMAP "main.bmp" // in .rc file
// showing icon in menu...
HBITMAP imgMain = LoadBitmap( aHinstance, MAKEINTRESOURCE(BITMAP_MAIN) );
SetMenuItemBitmaps ( hSubmenu, uMenuIndex, MF_BYPOSITION, imgMain, imgMain);
[main.bmp is 16X16]
- Also the icon(.bmp) is not shown fully in non-english OS.
So is there be any special technique to make the icon in the system context menu transparent like WinRAR?
You need a special mechanism for loading icons in Vista and later, since they don't seem to process (by default) transparencies in BMP files. You need to detect the operating system:
// Necessary for getting icons in the proper manner.
bool isVistaOrMore() {
OSVERSIONINFOEX inf;
SecureZeroMemory(&inf, sizeof(OSVERSIONINFOEX));
inf.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
WORD fullver = GetVersionEx((OSVERSIONINFO *)&inf);
return (fullver >= 0x0600);
}
If it returns false then do what you're doing right now, if it returns true, perform something analog to what's described in: http://msdn.microsoft.com/en-us/library/bb757020.aspx
I think TortoiseSVN uses owner-draw menus. Don't know about winrar, but this code might work even on win98 where TransparentBlt has memory leak. Bitmap must have color table (8-bit).
Use like this (this code formatting can mangle text, so check for errors!)
//we replace magenta with menu color ReplaceDIBColor(m_hMenuBmp, RGB(255,0,255), GetSysColor(COLOR_MENU));//function inline BOOL ReplaceDIBColor(HBITMAP &hDIB, COLORREF oldColor, COLORREF newColor) { BOOL bRet=FALSE; //get color information DIBSECTION ds; if (!GetObject(hDIB, sizeof(DIBSECTION), &ds)) return FALSE; if (ds.dsBmih.biBitCount>8) return FALSE; //must be 8 bpp max
HDC hDC=CreateCompatibleDC(NULL); if (!hDC) return FALSE; HBITMAP hbmpOld=(HBITMAP)::SelectObject(hDC, hDIB); //allocate color table UINT nColors = ds.dsBmih.biClrUsed ? ds.dsBmih.biClrUsed : 1<<ds.dsBmih.biBitCount; //bpp to UINT RGBQUAD* ptbl=(RGBQUAD*)CoTaskMemAlloc(nColors*sizeof(RGBQUAD)); if (ptbl) { if (GetDIBColorTable(hDC, 0, nColors, ptbl)) { //replace color table entries UINT i; for (i=0; i<nColors ; i++) { if (oldColor==RGB(ptbl[i].rgbRed, ptbl[i].rgbGreen, ptbl[i].rgbBlue)) { ptbl[i].rgbRed=GetRValue(newColor); ptbl[i].rgbGreen=GetGValue(newColor); ptbl[i].rgbBlue=GetBValue(newColor); bRet=TRUE; } } //set new table if (bRet) if (!SetDIBColorTable(hDC, 0, nColors, ptbl)) bRet=FALSE; } //cleanup CoTaskMemFree(ptbl); ptbl=NULL; bRet=TRUE; } else bRet=FALSE; hDIB=(HBITMAP)::SelectObject(hDC, hbmpOld); DeleteDC(hDC); return bRet; }
精彩评论