程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> 關於VC++ >> 透明位圖的顯示

透明位圖的顯示

編輯:關於VC++

包含透明色的位圖的繪制方法有多種,最簡單的方法是調用現成的函數:TransparentBlt,也可以通過自己的代碼實現類似TransparentBlt的功能,實現過程也有兩種形式,一種是事先做一張掩碼位圖,另一種是動態生成掩碼位圖。本文將介紹動態生成掩碼位圖繪制具有透明區域位圖的方法。

一、TransparentBlt 函數的使用

TransparentBlt 函數在Windows98/Windows2000以上版本運行,系統中需要包含 Msimg32.dll,使用時可以鏈接 Msimg32.lib。

Windows98下的TransparentBlt會產生資源洩漏,所以不建議在WIN98下使用該函數。

TransparentBlt函數原型如下:

BOOL TransparentBlt(
HDC hdcDest,   // 目標DC
int nXOriginDest,  // 目標X偏移
int nYOriginDest,  // 目標Y偏移
int nWidthDest,   // 目標寬度
int hHeightDest,  // 目標高度
HDC hdcSrc,     // 源DC
int nXOriginSrc,  // 源X起點
int nYOriginSrc,  // 源Y起點
int nWidthSrc,   // 源寬度
int nHeightSrc,   // 源高度
UINT crTransparent // 透明色,COLORREF類型
);

使用示例:

CBitmap FootballBMP;
FootballBMP.LoadBitmap(IDB_FOOTBALLBMP);
CDC ImageDC;
ImageDC.CreateCompatibleDC(pDC);
CBitmap *pOldImageBMP = ImageDC.SelectObject(&FootballBMP);
TransparentBlt(pDC->m_hDC, 0, 0, 218, 199, ImageDC.m_hDC, 0, 0, 218, 199, RGB(0,0,0xff));
ImageDC.SelectObject(pOldImageBMP);

二、實現TransparentBlt函數

為了理解具有透明色位圖的繪制過程,我們來親手建立一個具有同TransparentBlt功能一致的實驗函數,稱之為TransparentBlt2。

實驗素材:有兩張位圖:bk.bmp是背景位圖,football.bmp包含透明區域,透明色為藍色RGB(0,0,0xff)

實驗目的:以bk.bmp為背景,將football.bmp繪制到背景中,形成如下的最終效果圖。

2.1 透明位圖繪制原理

假設football.bmp ->載入 HBITMAP hImageBMP -> 選入 HDC hImageDC

2.1.1 生成足球的單色掩碼位圖,透明區域為白色(全1),非透明區域為黑色(全0)

HBITMAP hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 建立單色位圖
SetBkColor(hImageDC, RGB(0,0,0xff)); // 設置背景色為藍色
BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY); // 拷貝到hMaskDC

這樣足球位圖中藍色區域在掩碼位圖中成了白色,其它區域為黑色,此時hMaskBMP 如下圖:

(圖一)

2.1.2 設置背景色為黑色,前景色為白色,將掩碼位圖(圖一)與足球位圖相"與"

SetBkColor(hImageDC, RGB(0,0,0));
SetTextColor(hImageDC, RGB(255,255,255));
BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

這樣,掩碼位圖中背景色(黑色)的區域在hImageBMP中被保留,前景色(白色)的部分變為黑色。 此時hImageBMP 如下圖:

(圖二)

2.1.3 設置背景色為白色,前景色為黑色,將掩碼位圖(圖一)與背景進行“與”運算

SetBkColor(hdcDest,RGB(255,255,255));
SetTextColor(hdcDest,RGB(0,0,0));
BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

掩碼中白色區域(數據與1相“與”結果不變)使背景保持不變,黑色區域變成黑色,此時背景顯示如下:

(圖三)

2.1.4 將hImageBMP(圖二)與背景(圖三)進行“或”運算

BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);

這樣就將足球繪制到背景上了。

2.2 TransparentBlt2函數全部實現代碼

void TransparentBlt2( HDC hdcDest,   // 目標DC
          int nXOriginDest,  // 目標X偏移
          int nYOriginDest,  // 目標Y偏移
          int nWidthDest,   // 目標寬度
          int nHeightDest,  // 目標高度
          HDC hdcSrc,     // 源DC
          int nXOriginSrc,  // 源X起點
          int nYOriginSrc,  // 源Y起點
          int nWidthSrc,   // 源寬度
          int nHeightSrc,   // 源高度
          UINT crTransparent // 透明色,COLORREF類型
          )
{
  HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest);  // 創建兼容位圖
  HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);      // 創建單色掩碼位圖
  HDC    hImageDC = CreateCompatibleDC(hdcDest);
  HDC    hMaskDC = CreateCompatibleDC(hdcDest);
  hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
  hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);
  // 將源DC中的位圖拷貝到臨時DC中
  if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
    BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
  else
    StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest,
          hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
  // 設置透明色
  SetBkColor(hImageDC, crTransparent);
  // 生成透明區域為白色,其它區域為黑色的掩碼位圖
  BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);
  // 生成透明區域為黑色,其它區域保持不變的位圖
  SetBkColor(hImageDC, RGB(0,0,0));
  SetTextColor(hImageDC, RGB(255,255,255));
  BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
  // 透明部分保持屏幕不變,其它部分變成黑色
  SetBkColor(hdcDest,RGB(255,255,255));
  SetTextColor(hdcDest,RGB(0,0,0));
  BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
  // "或"運算,生成最終效果
  BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);
  // 清理、恢復  
  SelectObject(hImageDC, hOldImageBMP);
  DeleteDC(hImageDC);
  SelectObject(hMaskDC, hOldMaskBMP);
  DeleteDC(hMaskDC);
  DeleteObject(hImageBMP);
  DeleteObject(hMaskBMP);
}

2.3 TransparentBlt的另外一個版本:TransparentBltU

TransparentBltU是Christian Graus 在WinDEV發表的一個函數,功能與TransparentBlt一致,以下是全部實現代碼:

bool TransparentBltU(
   HDC dcDest,     // handle to Dest DC
   int nXOriginDest,  // x-coord of destination upper-left corner
   int nYOriginDest,  // y-coord of destination upper-left corner
   int nWidthDest,   // width of destination rectangle
   int nHeightDest,  // height of destination rectangle
   HDC dcSrc,     // handle to source DC
   int nXOriginSrc,  // x-coord of source upper-left corner
   int nYOriginSrc,  // y-coord of source upper-left corner
   int nWidthSrc,   // width of source rectangle
   int nHeightSrc,   // height of source rectangle
   UINT crTransparent // color to make transparent
 )
{
   if (nWidthDest < 1) return false;
   if (nWidthSrc < 1) return false;
   if (nHeightDest < 1) return false;
   if (nHeightSrc < 1) return false;
   HDC dc = CreateCompatibleDC(NULL);
   HBITMAP bitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, GetDeviceCaps(dc,
                               BITSPIXEL), NULL);
   if (bitmap == NULL)
   {
     DeleteDC(dc);  
     return false;
   }
   HBITMAP oldBitmap = (HBITMAP)SelectObject(dc, bitmap);
   if (!BitBlt(dc, 0, 0, nWidthSrc, nHeightSrc, dcSrc, nXOriginSrc,
                             nYOriginSrc, SRCCOPY))
   {
     SelectObject(dc, oldBitmap);
     DeleteObject(bitmap);    
     DeleteDC(dc);        
     return false;
   }
   HDC maskDC = CreateCompatibleDC(NULL);
   HBITMAP maskBitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, 1, NULL);
   if (maskBitmap == NULL)
   {
     SelectObject(dc, oldBitmap);
     DeleteObject(bitmap);    
     DeleteDC(dc);        
     DeleteDC(maskDC);      
     return false;
   }
   HBITMAP oldMask = (HBITMAP)SelectObject(maskDC, maskBitmap);
   SetBkColor(maskDC, RGB(0,0,0));
   SetTextColor(maskDC, RGB(255,255,255));
   if (!BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,NULL,0,0,BLACKNESS))
   {
     SelectObject(maskDC, oldMask);
     DeleteObject(maskBitmap);   
     DeleteDC(maskDC);       
     SelectObject(dc, oldBitmap); 
     DeleteObject(bitmap);     
     DeleteDC(dc);         
     return false;
   }
   SetBkColor(dc, crTransparent);
   BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,dc,0,0,SRCINVERT);
   SetBkColor(dc, RGB(0,0,0));
   SetTextColor(dc, RGB(255,255,255));
   BitBlt(dc, 0,0,nWidthSrc,nHeightSrc,maskDC,0,0,SRCAND);
   HDC newMaskDC = CreateCompatibleDC(NULL);
   HBITMAP newMask;
   newMask = CreateBitmap(nWidthDest, nHeightDest, 1,
                  GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
   if (newMask == NULL)
   {
     SelectObject(dc, oldBitmap);
     DeleteDC(dc);
     SelectObject(maskDC, oldMask);
     DeleteDC(maskDC);
     DeleteDC(newMaskDC);
     DeleteObject(bitmap);  
     DeleteObject(maskBitmap);
     return false;
   }
   SetStretchBltMode(newMaskDC, COLORONCOLOR);
   HBITMAP oldNewMask = (HBITMAP) SelectObject(newMaskDC, newMask);
   StretchBlt(newMaskDC, 0, 0, nWidthDest, nHeightDest, maskDC, 0, 0,
                        nWidthSrc, nHeightSrc, SRCCOPY);
   SelectObject(maskDC, oldMask);
   DeleteDC(maskDC);
   DeleteObject(maskBitmap);
   HDC newImageDC = CreateCompatibleDC(NULL);
   HBITMAP newImage = CreateBitmap(nWidthDest, nHeightDest, 1,
                  GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
   if (newImage == NULL)
   {
     SelectObject(dc, oldBitmap);
     DeleteDC(dc);
     DeleteDC(newMaskDC);
     DeleteObject(bitmap);  
     return false;
   }
   HBITMAP oldNewImage = (HBITMAP)SelectObject(newImageDC, newImage);
   StretchBlt(newImageDC, 0, 0, nWidthDest, nHeightDest, dc, 0, 0, nWidthSrc,
                             nHeightSrc, SRCCOPY);
   SelectObject(dc, oldBitmap);
   DeleteDC(dc);
   DeleteObject(bitmap);  
   BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                           newMaskDC, 0, 0, SRCAND);
   BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
                          newImageDC, 0, 0, SRCPAINT);
   SelectObject(newImageDC, oldNewImage);
   DeleteDC(newImageDC);
   SelectObject(newMaskDC, oldNewMask);
   DeleteDC(newMaskDC);
   DeleteObject(newImage); 
   DeleteObject(newMask);  
   return true;
}

說明:本文提供的TransparentBlt2函數旨在說明透明位圖的顯示原理,在Windows2000以上環境實際運用中建議使用現成的TransparentBlt函數來繪制透明位圖。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved