dwinkler
asked on
CreateIconIndirect
I have two bitmaps which I am passing. One is the mask (monochrome bitmap, 1 being the ON bit and 0 being the OFF bit). The other is the real bitmap image (actually a DIB created with CreateDIBSection). When the icon is displayed everything which is supposed to be transparent still comes up inverted. Any suggestions on this?
As I recall, transparency doesn't just depend on the mask--it also depends on the colour of the image bitmap at the same position. It's something like white is inverse and black is transparent, or possibly the other way round--anyway, you need to check what colour the "transparent" pixels are on your icon bitmap.
ASKER
So how do you use the mask? I want a certain color of the original bitmap to be transparent. Lets say, hypothetically, that RGB(255,0,255) is the background color. I want to create a icon that has that color as the transparency.
I think the background color is not important when using CreateIconIndirect.
Here comes an extract how I am using CreateIconIndirect. It's Delphi code, but I'm sure you can see the important things:
zeroMemory(@bi, sizeOf(TBitmapInfo));
with bi.bmiColors[1] do begin
rgbBlue := 255;
rgbGreen := 255;
rgbRed := 255;
end;
with bi.bmiHeader do begin
biSize := sizeOf(TBitmapInfoHeader);
biWidth := 32;
biHeight := 64;
biPlanes := 1;
biBitCount := 1;
biSizeImage := 256;
end;
This is how I prepare the monochrome bitmap. Please note that you have to set the bmiColors to the right values. bmiColors[0] must be all zero, while bmiColors[1] must be all $FF.
Regards, Madshi.
Here comes an extract how I am using CreateIconIndirect. It's Delphi code, but I'm sure you can see the important things:
zeroMemory(@bi, sizeOf(TBitmapInfo));
with bi.bmiColors[1] do begin
rgbBlue := 255;
rgbGreen := 255;
rgbRed := 255;
end;
with bi.bmiHeader do begin
biSize := sizeOf(TBitmapInfoHeader);
biWidth := 32;
biHeight := 64;
biPlanes := 1;
biBitCount := 1;
biSizeImage := 256;
end;
This is how I prepare the monochrome bitmap. Please note that you have to set the bmiColors to the right values. bmiColors[0] must be all zero, while bmiColors[1] must be all $FF.
Regards, Madshi.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
That's what I was missing...
I knew the mask should be a monochrome bitmap, but the doc didn't make it clear that the bitmap had to be the XOr image. BTW pImage is a generic class to hold bitmap info. The following code converts a standard bitmap with RGB(255,0,255) background into an icon with correct mask and image.
BITMAPINFO bmpInfoMem = { '\0' };
bmpInfoMem.bmiHeader.biSiz e = sizeof(BITMAPINFOHEADER);
bmpInfoMem.bmiHeader.biWid th = pImage->GetWidth( );
bmpInfoMem.bmiHeader.biHei ght = -(MOSINT32)pImage->GetHeig ht( );
bmpInfoMem.bmiHeader.biPla nes = 1;
bmpInfoMem.bmiHeader.biBit Count = 32;
bmpInfoMem.bmiHeader.biCom pression = BI_RGB;
HDC hClientDC = ::GetDC( NULL );
HDC hDCCreate = ::CreateCompatibleDC( hClientDC );
HDC hDCImage = ::CreateCompatibleDC( hClientDC );
HDC hDCAnd = ::CreateCompatibleDC( hClientDC );
HDC hDCXOr = ::CreateCompatibleDC( hClientDC );
HBITMAP hDDB = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hXOrBitmap = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hAndBitmap = ::CreateBitmap( pImage->GetWidth( ), pImage->GetHeight( ), 1, 1, NULL );
::SetDIBits( hDCCreate,
hDDB,
0,
pImage->GetHeight( ),
pImage->GetBuffer( ),
&bmpInfoMem,
DIB_RGB_COLORS );
::DeleteDC( hDCCreate );
// Create the AND Mask bitmap
HBITMAP hOldAndBitmap = (HBITMAP)::SelectObject( hDCAnd, hAndBitmap );
HBITMAP hOldImageBitmap = (HBITMAP)::SelectObject( hDCImage, hDDB );
HBITMAP hOldXorBitmap = (HBITMAP)::SelectObject( hDCXOr, hXOrBitmap );
// Create the monochrome mask bitmap from the source image using the background color
COLORREF crOld = ::SetBkColor( hDCImage, RGB(255,0,255) );
::BitBlt( hDCAnd, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::SetBkColor( hDCImage, crOld );
// Create the XOR color bitmap
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCAnd, 0, 0, 0x220326);
::SelectObject( hDCImage, hOldImageBitmap );
::SelectObject( hDCAnd, hOldAndBitmap );
::SelectObject( hDCXOr, hOldXorBitmap );
::DeleteDC( hDCXOr );
::DeleteDC( hDCImage );
::DeleteDC( hDCAnd );
::ReleaseDC( NULL, hClientDC );
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = hAndBitmap;
iconInfo.hbmColor = hXOrBitmap;
hIcon = ::CreateIconIndirect( &iconInfo );
::DeleteObject( hDDB );
::DeleteObject( hAndBitmap );
::DeleteObject( hXOrBitmap );
I knew the mask should be a monochrome bitmap, but the doc didn't make it clear that the bitmap had to be the XOr image. BTW pImage is a generic class to hold bitmap info. The following code converts a standard bitmap with RGB(255,0,255) background into an icon with correct mask and image.
BITMAPINFO bmpInfoMem = { '\0' };
bmpInfoMem.bmiHeader.biSiz
bmpInfoMem.bmiHeader.biWid
bmpInfoMem.bmiHeader.biHei
bmpInfoMem.bmiHeader.biPla
bmpInfoMem.bmiHeader.biBit
bmpInfoMem.bmiHeader.biCom
HDC hClientDC = ::GetDC( NULL );
HDC hDCCreate = ::CreateCompatibleDC( hClientDC );
HDC hDCImage = ::CreateCompatibleDC( hClientDC );
HDC hDCAnd = ::CreateCompatibleDC( hClientDC );
HDC hDCXOr = ::CreateCompatibleDC( hClientDC );
HBITMAP hDDB = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hXOrBitmap = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hAndBitmap = ::CreateBitmap( pImage->GetWidth( ), pImage->GetHeight( ), 1, 1, NULL );
::SetDIBits( hDCCreate,
hDDB,
0,
pImage->GetHeight( ),
pImage->GetBuffer( ),
&bmpInfoMem,
DIB_RGB_COLORS );
::DeleteDC( hDCCreate );
// Create the AND Mask bitmap
HBITMAP hOldAndBitmap = (HBITMAP)::SelectObject( hDCAnd, hAndBitmap );
HBITMAP hOldImageBitmap = (HBITMAP)::SelectObject( hDCImage, hDDB );
HBITMAP hOldXorBitmap = (HBITMAP)::SelectObject( hDCXOr, hXOrBitmap );
// Create the monochrome mask bitmap from the source image using the background color
COLORREF crOld = ::SetBkColor( hDCImage, RGB(255,0,255) );
::BitBlt( hDCAnd, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::SetBkColor( hDCImage, crOld );
// Create the XOR color bitmap
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCAnd, 0, 0, 0x220326);
::SelectObject( hDCImage, hOldImageBitmap );
::SelectObject( hDCAnd, hOldAndBitmap );
::SelectObject( hDCXOr, hOldXorBitmap );
::DeleteDC( hDCXOr );
::DeleteDC( hDCImage );
::DeleteDC( hDCAnd );
::ReleaseDC( NULL, hClientDC );
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = hAndBitmap;
iconInfo.hbmColor = hXOrBitmap;
hIcon = ::CreateIconIndirect( &iconInfo );
::DeleteObject( hDDB );
::DeleteObject( hAndBitmap );
::DeleteObject( hXOrBitmap );
ASKER
That's what I was missing...
I knew the mask should be a monochrome bitmap, but the doc didn't make it clear that the bitmap had to be the XOr image. BTW pImage is a generic class to hold bitmap info. The following code converts a standard bitmap with RGB(255,0,255) background into an icon with correct mask and image.
BITMAPINFO bmpInfoMem = { '\0' };
bmpInfoMem.bmiHeader.biSiz e = sizeof(BITMAPINFOHEADER);
bmpInfoMem.bmiHeader.biWid th = pImage->GetWidth( );
bmpInfoMem.bmiHeader.biHei ght = -(MOSINT32)pImage->GetHeig ht( );
bmpInfoMem.bmiHeader.biPla nes = 1;
bmpInfoMem.bmiHeader.biBit Count = 32;
bmpInfoMem.bmiHeader.biCom pression = BI_RGB;
HDC hClientDC = ::GetDC( NULL );
HDC hDCCreate = ::CreateCompatibleDC( hClientDC );
HDC hDCImage = ::CreateCompatibleDC( hClientDC );
HDC hDCAnd = ::CreateCompatibleDC( hClientDC );
HDC hDCXOr = ::CreateCompatibleDC( hClientDC );
HBITMAP hDDB = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hXOrBitmap = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hAndBitmap = ::CreateBitmap( pImage->GetWidth( ), pImage->GetHeight( ), 1, 1, NULL );
::SetDIBits( hDCCreate,
hDDB,
0,
pImage->GetHeight( ),
pImage->GetBuffer( ),
&bmpInfoMem,
DIB_RGB_COLORS );
::DeleteDC( hDCCreate );
// Create the AND Mask bitmap
HBITMAP hOldAndBitmap = (HBITMAP)::SelectObject( hDCAnd, hAndBitmap );
HBITMAP hOldImageBitmap = (HBITMAP)::SelectObject( hDCImage, hDDB );
HBITMAP hOldXorBitmap = (HBITMAP)::SelectObject( hDCXOr, hXOrBitmap );
// Create the monochrome mask bitmap from the source image using the background color
COLORREF crOld = ::SetBkColor( hDCImage, RGB(255,0,255) );
::BitBlt( hDCAnd, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::SetBkColor( hDCImage, crOld );
// Create the XOR color bitmap
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCAnd, 0, 0, 0x220326);
::SelectObject( hDCImage, hOldImageBitmap );
::SelectObject( hDCAnd, hOldAndBitmap );
::SelectObject( hDCXOr, hOldXorBitmap );
::DeleteDC( hDCXOr );
::DeleteDC( hDCImage );
::DeleteDC( hDCAnd );
::ReleaseDC( NULL, hClientDC );
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = hAndBitmap;
iconInfo.hbmColor = hXOrBitmap;
hIcon = ::CreateIconIndirect( &iconInfo );
::DeleteObject( hDDB );
::DeleteObject( hAndBitmap );
::DeleteObject( hXOrBitmap );
I knew the mask should be a monochrome bitmap, but the doc didn't make it clear that the bitmap had to be the XOr image. BTW pImage is a generic class to hold bitmap info. The following code converts a standard bitmap with RGB(255,0,255) background into an icon with correct mask and image.
BITMAPINFO bmpInfoMem = { '\0' };
bmpInfoMem.bmiHeader.biSiz
bmpInfoMem.bmiHeader.biWid
bmpInfoMem.bmiHeader.biHei
bmpInfoMem.bmiHeader.biPla
bmpInfoMem.bmiHeader.biBit
bmpInfoMem.bmiHeader.biCom
HDC hClientDC = ::GetDC( NULL );
HDC hDCCreate = ::CreateCompatibleDC( hClientDC );
HDC hDCImage = ::CreateCompatibleDC( hClientDC );
HDC hDCAnd = ::CreateCompatibleDC( hClientDC );
HDC hDCXOr = ::CreateCompatibleDC( hClientDC );
HBITMAP hDDB = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hXOrBitmap = ::CreateCompatibleBitmap( hClientDC, pImage->GetWidth( ), pImage->GetHeight( ) );
HBITMAP hAndBitmap = ::CreateBitmap( pImage->GetWidth( ), pImage->GetHeight( ), 1, 1, NULL );
::SetDIBits( hDCCreate,
hDDB,
0,
pImage->GetHeight( ),
pImage->GetBuffer( ),
&bmpInfoMem,
DIB_RGB_COLORS );
::DeleteDC( hDCCreate );
// Create the AND Mask bitmap
HBITMAP hOldAndBitmap = (HBITMAP)::SelectObject( hDCAnd, hAndBitmap );
HBITMAP hOldImageBitmap = (HBITMAP)::SelectObject( hDCImage, hDDB );
HBITMAP hOldXorBitmap = (HBITMAP)::SelectObject( hDCXOr, hXOrBitmap );
// Create the monochrome mask bitmap from the source image using the background color
COLORREF crOld = ::SetBkColor( hDCImage, RGB(255,0,255) );
::BitBlt( hDCAnd, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::SetBkColor( hDCImage, crOld );
// Create the XOR color bitmap
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCImage, 0, 0, SRCCOPY );
::BitBlt( hDCXOr, 0, 0, pImage->GetWidth( ), pImage->GetHeight( ), hDCAnd, 0, 0, 0x220326);
::SelectObject( hDCImage, hOldImageBitmap );
::SelectObject( hDCAnd, hOldAndBitmap );
::SelectObject( hDCXOr, hOldXorBitmap );
::DeleteDC( hDCXOr );
::DeleteDC( hDCImage );
::DeleteDC( hDCAnd );
::ReleaseDC( NULL, hClientDC );
ICONINFO iconInfo;
iconInfo.fIcon = TRUE;
iconInfo.xHotspot = 0;
iconInfo.yHotspot = 0;
iconInfo.hbmMask = hAndBitmap;
iconInfo.hbmColor = hXOrBitmap;
hIcon = ::CreateIconIndirect( &iconInfo );
::DeleteObject( hDDB );
::DeleteObject( hAndBitmap );
::DeleteObject( hXOrBitmap );
//Create color bitmap
hdc=GetDC(NULL);
ii.hbmColor=CreateDIBitmap
//Create mask bitmap (monochrome)
pBmih->biBitCount=1;
pBmih->biClrUsed=0;
ii.hbmMask=CreateBitmap(pB
SetDIBits(hdc,ii.hbmMask,0
ReleaseDC(NULL,hdc);
//Create the icon
ii.fIcon=TRUE;
ii.xHotspot=ii.yHotspot=0;
hIcon=CreateIconIndirect(&
In the above I'm initialising the contents of the bitmaps directly from raw data but thats should be irelevant. How similar is the above to your code?