// when blitting from a monochrome DC to a color DC, // the color black in the source turns into the destination's text color, // and the color white in the source turns into the destination's background color. // If you blit from a color DC to a monochrome DC, // then all pixels in the source that are equal to the background color will turn white, and all other pixels will turn black. // In other words, GDI considers a monochrome bitmap to be black pixels on a white background. static void DrawTransBmp( HDC hDst, HBITMAP hImg, COLORREF clrTran ) { COLORREF colorOldFront; COLORREF colorOldBg; BITMAP bmp; GetObject( hImg, sizeof( bmp ), &bmp ); HDC hForeDC = ::CreateCompatibleDC( hDst ); ::SelectObject ( hForeDC, hImg ); //prepare mask dc HDC hDCMask = CreateCompatibleDC ( hDst ); // MSDN: When a memory device context is created, it initially has a 1-by-1 monochrome bitmap selected into it. // If this memory device context is used in CreateCompatibleBitmap, the bitmap that is created is a monochrome bitmap. HBITMAP hBmpMask = CreateCompatibleBitmap( hDCMask, bmp.bmWidth, bmp.bmHeight ); ::SelectObject ( hDCMask, hBmpMask ); ::SetBkColor( hForeDC, clrTran ); //Set clrTran as blackground color ::BitBlt( hDCMask, 0, 0, bmp.bmWidth, bmp.bmHeight, hForeDC, 0, 0, SRCCOPY ); //monochrome, background color is white //mask the foreground ::SetBkColor( hForeDC, RGB(0,0,0) ); ::SetTextColor( hForeDC, RGB(255,255,255) ); ::BitBlt( hForeDC, 0, 0, bmp.bmWidth, bmp.bmHeight, hDCMask, 0, 0, SRCAND ); //mask the background colorOldBg = ::SetBkColor( hDst, RGB(255,255,255) ); colorOldFront = ::SetTextColor( hDst, RGB(0,0,0) ); ::BitBlt( hDst, 0, 0, bmp.bmWidth, bmp.bmHeight, hDCMask, 0, 0, SRCAND ); //or foreground and background ::BitBlt( hDst, 0, 0, bmp.bmWidth, bmp.bmHeight, hForeDC, 0, 0, SRCPAINT ); //recover hDst color of background and foreground ::SetBkColor( hDst, colorOldBg ); ::SetTextColor( hDst, colorOldFront ); //release object ::DeleteDC( hDCMask ); ::DeleteDC( hForeDC ); ::DeleteObject( hBmpMask ); }