// BitmapEx.cpp: implementation of the CBitmapEx class. // // History: // 2002.11.23 // copy from kdphoto projects // // // // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "BitmapEx.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif const int HIMETRIC_INCH = 2540; // TransparentBlt - Copies a bitmap transparently onto the destination DC // hdcDest - Handle to destination device context // nXDest - x-coordinate of destination rectangle's upper-left corner // nYDest - y-coordinate of destination rectangle's upper-left corner // nWidth - Width of destination rectangle // nHeight - height of destination rectangle // hBitmap - Handle of the source bitmap // nXSrc - x-coordinate of source rectangle's upper-left corner // nYSrc - y-coordinate of source rectangle's upper-left corner // colorTransparent - The transparent color // hPal - Logical palette to be used with bitmap. Can be NULL void MyTransparentBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, COLORREF colorTransparent, HPALETTE hPal ) { /* CDC dc; dc.Attach (hdcDest); CDC memdc, maskdc; CBitmap Image, *oldImage; CBitmap MaskImage, *oldMaskImage; memdc.CreateCompatibleDC (&dc); maskdc.CreateCompatibleDC (&dc); Image.Attach (hBitmap); MaskImage.CreateBitmap (nWidth, nHeight, 1, 1, NULL); oldImage=memdc.SelectObject (&Image); oldMaskImage=maskdc.SelectObject (&MaskImage); memdc.SetBkColor (colorTransparent); maskdc.BitBlt (0, 0, nWidth, nHeight, &memdc, 0, 0, SRCCOPY); memdc.SetBkColor (RGB(0,0,0)); memdc.SetTextColor (RGB(255,255,255)); memdc.BitBlt (0, 0, nWidth, nHeight, &maskdc, 0, 0, SRCAND); dc.BitBlt (nXDest, nYDest, nWidth, nHeight, &maskdc, 0, 0, SRCAND); dc.BitBlt (nXDest, nYDest, nWidth, nHeight, &memdc, 0, 0, SRCPAINT); memdc.SelectObject (oldImage); maskdc.SelectObject (oldMaskImage); Image.Detach (); dc.Detach ();*/ CDC dc, memDC, maskDC, tempDC; dc.Attach( hdcDest ); maskDC.CreateCompatibleDC(&dc); CBitmap maskBitmap; //add these to store return of SelectObject() calls CBitmap* pOldMemBmp = NULL; CBitmap* pOldMaskBmp = NULL; HBITMAP hOldTempBmp = NULL; memDC.CreateCompatibleDC(&dc); tempDC.CreateCompatibleDC(&dc); CBitmap bmpImage; bmpImage.CreateCompatibleBitmap( &dc, nWidth, nHeight ); pOldMemBmp = memDC.SelectObject( &bmpImage ); // Select and realize the palette if( dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE && hPal ) { ::SelectPalette( dc, hPal, FALSE ); dc.RealizePalette(); ::SelectPalette( memDC, hPal, FALSE ); } hOldTempBmp = (HBITMAP) ::SelectObject( tempDC.m_hDC, hBitmap ); memDC.BitBlt( 0,0,nWidth, nHeight, &tempDC, nXSrc, nYSrc, SRCCOPY ); // Create monochrome bitmap for the mask maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL ); pOldMaskBmp = maskDC.SelectObject( &maskBitmap ); memDC.SetBkColor( colorTransparent ); // Create the mask from the memory DC maskDC.BitBlt( 0, 0, nWidth, nHeight, &memDC, 0, 0, SRCCOPY ); // Set the background in memDC to black. Using SRCPAINT with black // and any other color results in the other color, thus making // black the transparent color memDC.SetBkColor(RGB(0,0,0)); memDC.SetTextColor(RGB(255,255,255)); memDC.BitBlt(0, 0, nWidth, nHeight, &maskDC, 0, 0, SRCAND); // Set the foreground to black. See comment above. dc.SetBkColor(RGB(255,255,255)); dc.SetTextColor(RGB(0,0,0)); dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &maskDC, 0, 0, SRCAND); // Combine the foreground with the background dc.BitBlt(nXDest, nYDest, nWidth, nHeight, &memDC, 0, 0, SRCPAINT); if (hOldTempBmp) ::SelectObject( tempDC.m_hDC, hOldTempBmp); if (pOldMaskBmp) maskDC.SelectObject( pOldMaskBmp ); if (pOldMemBmp) memDC.SelectObject( pOldMemBmp ); dc.Detach(); } /* void MyTransparentBlt( HDC hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, HBITMAP hBitmap, int nXSrc, int nYSrc, COLORREF colorTransparent, HPALETTE hPal ) { CDC *pDC =CDC::FromHandle(hdcDest); CDC ImageDC,MaskDC; CBitmap Image,*pOldImage; CBitmap maskBitmap,*pOldMaskDCBitmap ; Image.Attach (hBitmap); ImageDC.CreateCompatibleDC(pDC); pOldImage=ImageDC.SelectObject(&Image); MaskDC.CreateCompatibleDC(pDC); maskBitmap.CreateBitmap( nWidth, nHeight, 1, 1, NULL ); pOldMaskDCBitmap = MaskDC.SelectObject( &maskBitmap ); ImageDC.SetBkColor(colorTransparent); MaskDC.BitBlt( 0, 0, nWidth, nHeight, &ImageDC, 0, 0, SRCCOPY ); ImageDC.SetBkColor(RGB(0,0,0)); ImageDC.SetTextColor(RGB(255,255,255)); ImageDC.BitBlt(0, 0, nWidth, nHeight, &MaskDC, 0, 0, SRCAND); pDC->BitBlt(nXDest,nYDest,nWidth, nHeight, &MaskDC, 0, 0, SRCAND); pDC->BitBlt(nXDest,nYDest,nWidth, nHeight, &ImageDC, 0, 0,SRCPAINT); MaskDC.SelectObject(pOldMaskDCBitmap); ImageDC.SelectObject(pOldImage); Image.Detach (); }*/ ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CBitmapEx::CBitmapEx() { } CBitmapEx::~CBitmapEx() { } BOOL CBitmapEx::StretchDraw(CDC *pDC, LPRECT r, LPRECT sr ) { if ( !r ) return FALSE; CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap * bmp = dc.SelectObject( this ); pDC->SetStretchBltMode(COLORONCOLOR); if ( !sr ) pDC->StretchBlt( r->left, r->top, r->right, r->bottom, &dc, 0, 0, GetWidth(), GetHeight() , SRCCOPY ); else pDC->StretchBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, sr->left, sr->top, sr->right - sr->left, sr->bottom - sr->top, SRCCOPY ); dc.SelectObject( bmp ); return TRUE; } BOOL CBitmapEx::StretchDraw(CDC *pDC, LPRECT r) { CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap * bmp = dc.SelectObject( this ); // pDC->StretchBlt( r->left, r->top, r->right-r->left, r->bottom -r->top , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY ); pDC->StretchBlt( r->left, r->top, r->right-r->left, GetHeight() , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY ); dc.SelectObject( bmp ); return TRUE; } BOOL CBitmapEx::StretchDraw2(CDC *pDC, LPRECT r) { CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap * bmp = dc.SelectObject( this ); // pDC->StretchBlt( r->left, r->top, r->right-r->left, r->bottom -r->top , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY ); pDC->StretchBlt( r->left, r->top, GetWidth(), r->bottom -r->top , &dc, 0, 0, GetWidth(), GetHeight() ,SRCCOPY ); dc.SelectObject( bmp ); return TRUE; } BOOL CBitmapEx::Draw( CDC *pDC, int x, int y, LPRECT sr, COLORREF colTrans, BOOL bTrans ) { if ( !bTrans ) Draw( pDC ,x, y, sr ); else { MyTransparentBlt( pDC->GetSafeHdc(), x, y, sr->right - sr->left, sr->bottom - sr->top, (HBITMAP)this->GetSafeHandle(), sr->left, sr->top, colTrans, NULL ); } return TRUE; } //draw sub bmp to special point BOOL CBitmapEx::Draw( CDC *pDC, int x, int y, LPRECT sr ) { CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap * bmp = dc.SelectObject( this ); if ( sr != NULL) pDC->BitBlt( x, y, sr->right - sr->left, sr->bottom - sr->top, &dc, sr->left, sr->top, SRCCOPY ); else pDC->BitBlt( x, y, Width(), Height(), &dc, 0, 0, SRCCOPY ); dc.SelectObject( bmp ); return TRUE; } BOOL CBitmapEx::Draw(CDC *pDC, LPRECT r) { CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap * bmp = dc.SelectObject( this ); pDC->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, 0, 0 , SRCCOPY ); dc.SelectObject( bmp ); return TRUE; } BOOL CBitmapEx::Draw(CDC *pDC, LPRECT r, int pos) { CDC dc; dc.CreateCompatibleDC( pDC ); CBitmap * bmp = dc.SelectObject( this ); pDC->BitBlt( r->left, r->top, r->right - r->left, r->bottom - r->top, &dc, pos, 0 , SRCCOPY ); dc.SelectObject( bmp ); return TRUE; } ///HOWTO: Drawing Transparent Bitmaps //see: Microsoft Knowledge Base Article - Q79212 BOOL CBitmapEx::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour) { MyTransparentBlt( pDC->GetSafeHdc(), x, y, GetWidth(), GetHeight(), (HBITMAP)this->GetSafeHandle(), 0, 0, crColour, NULL ); /* COLORREF crOldBack = pDC->SetBkColor(0); COLORREF crOldText = pDC->SetTextColor(RGB(255,255,255)); CDC dcImage, dcTrans; // Create two memory dcs for the image and the mask dcImage.CreateCompatibleDC(pDC); dcTrans.CreateCompatibleDC(pDC); // Select the image into the appropriate dc CBitmap* pOldBitmapImage = dcImage.SelectObject(this); // Create the mask bitmap CBitmap bitmapTrans; int nWidth = GetWidth(); int nHeight = GetHeight(); bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL); // Select the mask bitmap into the appropriate dc CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans); // Build mask based on transparent colour dcImage.SetBkColor(crColour); dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY); // Do the work - True Mask method - cool if not actual display pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT); pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND); pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT); // Restore settings dcImage.SelectObject(pOldBitmapImage); dcTrans.SelectObject(pOldBitmapTrans); pDC->SetBkColor(crOldBack); pDC->SetTextColor(crOldText); */ return TRUE; } HRGN CBitmapEx::CreateRgnFromFile( COLORREF color ) { HBITMAP hBmp = (HBITMAP)this->GetSafeHandle(); // get image properties BITMAP bmp = { 0 }; ::GetObject( hBmp, sizeof(BITMAP), &bmp ); // allocate memory for extended image information LPBITMAPINFO bi = (LPBITMAPINFO) new BYTE[ sizeof(BITMAPINFO) + 8 ]; memset( bi, 0, sizeof(BITMAPINFO) + 8 ); bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); // set window size int m_dwWidth = bmp.bmWidth; // bitmap width int m_dwHeight = bmp.bmHeight; // bitmap height // create temporary dc HDC dc = CreateIC( "DISPLAY",NULL,NULL,NULL ); // get extended information about image (length, compression, length of color table if exist, ...) DWORD res = GetDIBits( dc, hBmp, 0, bmp.bmHeight, 0, bi, DIB_RGB_COLORS ); // allocate memory for image data (colors) LPBYTE pBits = new BYTE[ bi->bmiHeader.biSizeImage + 4 ]; // allocate memory for color table if ( bi->bmiHeader.biBitCount == 8 ) { // actually color table should be appended to this header(BITMAPINFO), // so we have to reallocate and copy it LPBITMAPINFO old_bi = bi; // 255 - because there is one in BITMAPINFOHEADER bi = (LPBITMAPINFO)new char[ sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD) ]; memcpy( bi, old_bi, sizeof(BITMAPINFO) ); // release old header delete old_bi; } // get bitmap info header BITMAPINFOHEADER& bih = bi->bmiHeader; // get color table (for 256 color mode contains 256 entries of RGBQUAD(=DWORD)) LPDWORD clr_tbl = (LPDWORD)&bi->bmiColors; // fill bits buffer res = GetDIBits( dc, hBmp, 0, bih.biHeight, pBits, bi, DIB_RGB_COLORS ); DeleteDC( dc ); BITMAP bm; ::GetObject( hBmp, sizeof(BITMAP), &bm ); // shift bits and byte per pixel (for comparing colors) LPBYTE pClr = (LPBYTE)&color; // swap red and blue components BYTE tmp = pClr[0]; pClr[0] = pClr[2]; pClr[2] = tmp; // convert color if curent DC is 16-bit (5:6:5) or 15-bit (5:5:5) if ( bih.biBitCount == 16 ) { // for 16 bit color = ((DWORD)(pClr[0] & 0xf8) >> 3) | ((DWORD)(pClr[1] & 0xfc) << 3) | ((DWORD)(pClr[2] & 0xf8) << 8); // for 15 bit // color = ((DWORD)(pClr[0] & 0xf8) >> 3) | // ((DWORD)(pClr[1] & 0xf8) << 2) | // ((DWORD)(pClr[2] & 0xf8) << 7); } const DWORD RGNDATAHEADER_SIZE = sizeof(RGNDATAHEADER); const DWORD ADD_RECTS_COUNT = 40; // number of rects to be appended // to region data buffer // BitPerPixel BYTE Bpp = bih.biBitCount >> 3; // bytes per pixel // bytes per line in pBits is DWORD aligned and bmp.bmWidthBytes is WORD aligned // so, both of them not DWORD m_dwAlignedWidthBytes = (bmp.bmWidthBytes & ~0x3) + (!!(bmp.bmWidthBytes & 0x3) << 2); // DIB image is flipped that's why we scan it from the last line LPBYTE pColor = pBits + (bih.biHeight - 1) * m_dwAlignedWidthBytes; DWORD dwLineBackLen = m_dwAlignedWidthBytes + bih.biWidth * Bpp; // offset of previous scan line // (after processing of current) DWORD dwRectsCount = bih.biHeight; // number of rects in allocated buffer INT i, j; // current position in mask image INT first = 0; // left position of current scan line // where mask was found bool wasfirst = false; // set when mask has been found in current scan line bool ismask; // set when current color is mask color // allocate memory for region data // region data here is set of regions that are rectangles with height 1 pixel (scan line) // that's why first allocation is RECTs - number of scan lines in image RGNDATAHEADER* pRgnData = (RGNDATAHEADER*)new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ]; // get pointer to RECT table LPRECT pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE); // zero region data header memory (header part only) memset( pRgnData, 0, RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ); // fill it by default pRgnData->dwSize = RGNDATAHEADER_SIZE; pRgnData->iType = RDH_RECTANGLES; for ( i = 0; i < bih.biHeight; i++ ) { for ( j = 0; j < bih.biWidth; j++ ) { // get color switch ( bih.biBitCount ) { case 8: ismask = (clr_tbl[ *pColor ] != color); break; case 16: ismask = (*(LPWORD)pColor != (WORD)color); break; case 24: ismask = ((*(LPDWORD)pColor & 0x00ffffff) != color); break; case 32: ismask = (*(LPDWORD)pColor != color); } // shift pointer to next color pColor += Bpp; // place part of scan line as RECT region if transparent color found after mask color or // mask color found at the end of mask image if ( wasfirst ) { if ( !ismask ) { // save current RECT pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 ); // if buffer full reallocate it with more room if ( pRgnData->nCount >= dwRectsCount ) { dwRectsCount += ADD_RECTS_COUNT; // allocate new buffer LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ]; // copy current region data to it memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) ); // delte old region data buffer delete pRgnData; // set pointer to new regiondata buffer to current pRgnData = (RGNDATAHEADER*)pRgnDataNew; // correct pointer to RECT table pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE); } wasfirst = false; } } else if ( ismask ) // set wasfirst when mask is found { first = j; wasfirst = true; } } if ( wasfirst && ismask ) { // save current RECT pRects[ pRgnData->nCount++ ] = CRect( first, i, j, i + 1 ); // if buffer full reallocate it with more room if ( pRgnData->nCount >= dwRectsCount ) { dwRectsCount += ADD_RECTS_COUNT; // allocate new buffer LPBYTE pRgnDataNew = new BYTE[ RGNDATAHEADER_SIZE + dwRectsCount * sizeof(RECT) ]; // copy current region data to it memcpy( pRgnDataNew, pRgnData, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT) ); // delte old region data buffer delete pRgnData; // set pointer to new regiondata buffer to current pRgnData = (RGNDATAHEADER*)pRgnDataNew; // correct pointer to RECT table pRects = (LPRECT)((LPBYTE)pRgnData + RGNDATAHEADER_SIZE); } wasfirst = false; } pColor -= dwLineBackLen; } // release image data delete pBits; delete bi; // create region HRGN hRgn = ExtCreateRegion( NULL, RGNDATAHEADER_SIZE + pRgnData->nCount * sizeof(RECT), (LPRGNDATA)pRgnData ); // release region data delete pRgnData; return hRgn; } BOOL CBitmapEx::LoadImage(UINT uIDRes, LPCTSTR szResourceType, HMODULE hInst, COLORREF crBack) { ASSERT(m_hObject == NULL); // only attach once, detach on destroy if (m_hObject != NULL) return FALSE; BYTE* pBuff = NULL; int nSize = 0; BOOL bResult = FALSE; // first call is to get buffer size if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, 0, nSize)) { if (nSize > 0) { pBuff = new BYTE[nSize]; // this loads it if (GetResource(MAKEINTRESOURCE(uIDRes), szResourceType, hInst, pBuff, nSize)) { IPicture* pPicture = LoadFromBuffer(pBuff, nSize); if (pPicture) { bResult = Attach(pPicture, crBack); pPicture->Release(); } } delete [] pBuff; } } return bResult; } BOOL CBitmapEx::LoadImage(LPCTSTR szImagePath, COLORREF crBack) { ASSERT(m_hObject == NULL); // only attach once, detach on destroy if (m_hObject != NULL) return FALSE; BOOL bResult = FALSE; CFile cFile; CFileException e; if (cFile.Open(szImagePath, CFile::modeRead | CFile::typeBinary, &e)) { int nSize = cFile.GetLength(); BYTE* pBuff = new BYTE[nSize]; if (cFile.Read(pBuff, nSize) > 0) { IPicture* pPicture = LoadFromBuffer(pBuff, nSize); if (pPicture) { bResult = Attach(pPicture, crBack); pPicture->Release(); } } delete [] pBuff; } return bResult; } IPicture* CBitmapEx::LoadFromBuffer(BYTE* pBuff, int nSize) { bool bResult = false; HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, nSize); void* pData = GlobalLock(hGlobal); memcpy(pData, pBuff, nSize); GlobalUnlock(hGlobal); IStream* pStream = NULL; IPicture* pPicture = NULL; if (CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) == S_OK) { HRESULT hr = OleLoadPicture(pStream, nSize, FALSE, IID_IPicture, (LPVOID *)&pPicture); pStream->Release(); } return pPicture; // caller releases } BOOL CBitmapEx::GetResource(LPCTSTR lpName, LPCTSTR lpType, HMODULE hInst, void* pResource, int& nBufSize) { HRSRC hResInfo; HANDLE hRes; LPSTR lpRes = NULL; int nLen = 0; bool bResult = FALSE; // Find the resource hResInfo = FindResource(hInst, lpName, lpType); if (hResInfo == NULL) return false; // Load the resource hRes = LoadResource(hInst, hResInfo); if (hRes == NULL) return false; // Lock the resource lpRes = (char*)LockResource(hRes); if (lpRes != NULL) { if (pResource == NULL) { nBufSize = SizeofResource(hInst, hResInfo); bResult = true; } else { if (nBufSize >= (int)SizeofResource(hInst, hResInfo)) { memcpy(pResource, lpRes, nBufSize); bResult = true; } } UnlockResource(hRes); } // Free the resource FreeResource(hRes); return bResult; } BOOL CBitmapEx::Attach(IPicture* pPicture, COLORREF crBack) { ASSERT(m_hObject == NULL); // only attach once, detach on destroy if (m_hObject != NULL) return FALSE; ASSERT(pPicture); if (!pPicture) return FALSE; BOOL bResult = FALSE; CDC dcMem; CDC* pDC = CWnd::GetDesktopWindow()->GetDC(); if (dcMem.CreateCompatibleDC(pDC)) { long hmWidth; long hmHeight; pPicture->get_Width(&hmWidth); pPicture->get_Height(&hmHeight); int nWidth = MulDiv(hmWidth, pDC->GetDeviceCaps(LOGPIXELSX), HIMETRIC_INCH); int nHeight = MulDiv(hmHeight, pDC->GetDeviceCaps(LOGPIXELSY), HIMETRIC_INCH); CBitmap bmMem; if (bmMem.CreateCompatibleBitmap(pDC, nWidth, nHeight)) { CBitmap* pOldBM = dcMem.SelectObject(&bmMem); if (crBack != -1) dcMem.FillSolidRect(0, 0, nWidth, nHeight, crBack); HRESULT hr = pPicture->Render(dcMem, 0, 0, nWidth, nHeight, 0, hmHeight, hmWidth, -hmHeight, NULL); dcMem.SelectObject(pOldBM); if (hr == S_OK) bResult = CBitmap::Attach(bmMem.Detach()); } } CWnd::GetDesktopWindow()->ReleaseDC(pDC); return bResult; } HBITMAP CreateBitmapMask(HBITMAP hSourceBitmap, DWORD dwWidth, DWORD dwHeight, COLORREF crTransColor) { HBITMAP hMask = NULL; HDC hdcSrc = NULL; HDC hdcDest = NULL; HBITMAP hbmSrcT = NULL; HBITMAP hbmDestT = NULL; COLORREF crSaveBk; COLORREF crSaveDestText; hMask = ::CreateBitmap(dwWidth, dwHeight, 1, 1, NULL); if (hMask == NULL) return NULL; hdcSrc = ::CreateCompatibleDC(NULL); hdcDest = ::CreateCompatibleDC(NULL); hbmSrcT = (HBITMAP)::SelectObject(hdcSrc, hSourceBitmap); hbmDestT = (HBITMAP)::SelectObject(hdcDest, hMask); crSaveBk = ::SetBkColor(hdcSrc, crTransColor); ::BitBlt(hdcDest, 0, 0, dwWidth, dwHeight, hdcSrc, 0, 0, SRCCOPY); crSaveDestText = ::SetTextColor(hdcSrc, RGB(255, 255, 255)); ::SetBkColor(hdcSrc,RGB(0, 0, 0)); ::BitBlt(hdcSrc, 0, 0, dwWidth, dwHeight, hdcDest, 0, 0, SRCAND); SetTextColor(hdcDest, crSaveDestText); ::SetBkColor(hdcSrc, crSaveBk); ::SelectObject(hdcSrc, hbmSrcT); ::SelectObject(hdcDest, hbmDestT); ::DeleteDC(hdcSrc); ::DeleteDC(hdcDest); return hMask; } // End of CreateBitmapMask void CBitmapEx::TransParentDraw(CDC *pDC, CRect rc, COLORREF col) { HDC hdc; hdc=pDC->m_hDC ; HBITMAP hbmp=(HBITMAP)this->m_hObject; MyTransparentBlt( hdc, rc.left , rc.top ,rc.Width (), rc.Height (), hbmp, 0, 0, col, NULL ); } /* //这是一个用来画透明位图的函数 //CDC *pDC 需要画位图的CDC指针 //UINT IDImage 位图资源ID //CRect &rect 指定位图在pDC中的位置 //COLORREF rgbMask 位图的透明色 void DrawTransparentBitmap(CDC *pDC, UINT IDImage,CRect &rect, COLORREF rgbMask) { CDC ImageDC,MaskDC; CBitmap Image,*pOldImage; CBitmap maskBitmap,*pOldMaskDCBitmap ; Image.LoadBitmap(IDImage); ImageDC.CreateCompatibleDC(pDC); pOldImage=ImageDC.SelectObject(&Image); MaskDC.CreateCompatibleDC(pDC); maskBitmap.CreateBitmap( rect.Width(), rect.Height(), 1, 1, NULL ); pOldMaskDCBitmap = MaskDC.SelectObject( &maskBitmap ); ImageDC.SetBkColor(rgbMask); MaskDC.BitBlt( 0, 0, rect.Width(), rect.Height(), &ImageDC, 0, 0, SRCCOPY ); ImageDC.SetBkColor(RGB(0,0,0)); ImageDC.SetTextColor(RGB(255,255,255)); ImageDC.BitBlt(0, 0, rect.Width(), rect.Height(), &MaskDC, 0, 0, SRCAND); pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height(), &MaskDC, 0, 0, SRCAND); pDC->BitBlt(rect.left,rect.top,rect.Width(), rect.Height(), &ImageDC, 0, 0,SRCPAINT); MaskDC.SelectObject(pOldMaskDCBitmap); ImageDC.SelectObject(pOldImage); } */