Link to home
Start Free TrialLog in
Avatar of dwinkler
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?
Avatar of robpitt
robpitt

Heres a fragment of code that I've used that works:

   //Create color bitmap
    hdc=GetDC(NULL);
    ii.hbmColor=CreateDIBitmap(hdc,pBmih,CBM_INIT,pColorData,pBmi,DIB_RGB_COLORS);    

    //Create mask bitmap (monochrome)
    pBmih->biBitCount=1;
    pBmih->biClrUsed=0;
    ii.hbmMask=CreateBitmap(pBmih->biWidth,pBmih->biHeight,1,1,NULL);
    SetDIBits(hdc,ii.hbmMask,0,32,pMaskData,pBmi,DIB_RGB_COLORS);    
    ReleaseDC(NULL,hdc);
       
    //Create the icon
    ii.fIcon=TRUE;
    ii.xHotspot=ii.yHotspot=0;
    hIcon=CreateIconIndirect(&ii);


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?

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.
Avatar of dwinkler

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.
ASKER CERTIFIED SOLUTION
Avatar of robpitt
robpitt

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.biSize               = sizeof(BITMAPINFOHEADER);
bmpInfoMem.bmiHeader.biWidth          = pImage->GetWidth( );
bmpInfoMem.bmiHeader.biHeight          = -(MOSINT32)pImage->GetHeight( );
bmpInfoMem.bmiHeader.biPlanes          = 1;
bmpInfoMem.bmiHeader.biBitCount          = 32;
bmpInfoMem.bmiHeader.biCompression     = 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 );
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.biSize               = sizeof(BITMAPINFOHEADER);
bmpInfoMem.bmiHeader.biWidth          = pImage->GetWidth( );
bmpInfoMem.bmiHeader.biHeight          = -(MOSINT32)pImage->GetHeight( );
bmpInfoMem.bmiHeader.biPlanes          = 1;
bmpInfoMem.bmiHeader.biBitCount          = 32;
bmpInfoMem.bmiHeader.biCompression     = 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 );