透明位圖的顯示

轉自:http://www.vckbase.com/index.php/wv/358.html

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

一、TransparentBlt 函數的使用

TransparentBlt 函數在Windows98/Windows2000以上版本運行,系統中需要包含 Msimg32.dll,使用時可以鏈接 Msimg32.lib。
Windows98下的TransparentBlt會產生資源泄漏,所以不建議在WIN98下使用該函數。

TransparentBlt函數原型如下:

01.BOOL TransparentBlt(
02.HDC hdcDest,      // 目標DC
03.int nXOriginDest,   // 目標X偏移
04.int nYOriginDest,   // 目標Y偏移
05.int nWidthDest,     // 目標寬度
06.int hHeightDest,    // 目標高度
07.HDC hdcSrc,         // 源DC
08.int nXOriginSrc,    // 源X起點
09.int nYOriginSrc,    // 源Y起點
10.int nWidthSrc,      // 源寬度
11.int nHeightSrc,     // 源高度
12.UINT crTransparent  // 透明色,COLORREF類型
13.);

使用示例:

1.CBitmap FootballBMP;
2.FootballBMP.LoadBitmap(IDB_FOOTBALLBMP);
3.CDC ImageDC;
4.ImageDC.CreateCompatibleDC(pDC);
5.CBitmap *pOldImageBMP = ImageDC.SelectObject(&FootballBMP);
6.TransparentBlt(pDC->m_hDC, 0, 0, 218, 199, ImageDC.m_hDC, 0, 0, 218, 199, RGB(0,0,0xff));
7.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)

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

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

(圖一)

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

1.SetBkColor(hImageDC, RGB(0,0,0));
2.SetTextColor(hImageDC, RGB(255,255,255));
3.BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);

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

(圖二)

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

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

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

(圖三)

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

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

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

2.2 TransparentBlt2函數全部實現代碼

01.void TransparentBlt2( HDC hdcDest,      // 目標DC
02.int nXOriginDest,   // 目標X偏移
03.int nYOriginDest,   // 目標Y偏移
04.int nWidthDest,     // 目標寬度
05.int nHeightDest,    // 目標高度
06.HDC hdcSrc,         // 源DC
07.int nXOriginSrc,    // 源X起點
08.int nYOriginSrc,    // 源Y起點
09.int nWidthSrc,      // 源寬度
10.int nHeightSrc,     // 源高度
11.UINT crTransparent  // 透明色,COLORREF類型
12.)
13.{
14.HBITMAP hOldImageBMP, hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); // 創建兼容位圖
15.HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);          // 創建單色掩碼位圖
16.HDC     hImageDC = CreateCompatibleDC(hdcDest);
17.HDC     hMaskDC = CreateCompatibleDC(hdcDest);
18.hOldImageBMP = (HBITMAP)SelectObject(hImageDC, hImageBMP);
19.hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);
20. 
21.// 將源DC中的位圖拷貝到臨時DC中
22.if (nWidthDest == nWidthSrc && nHeightDest == nHeightSrc)
23.BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);
24.else
25.StretchBlt(hImageDC, 0, 0, nWidthDest, nHeightDest,
26.hdcSrc, nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);
27. 
28.// 設置透明色
29.SetBkColor(hImageDC, crTransparent);
30. 
31.// 生成透明區域爲白色,其它區域爲黑色的掩碼位圖
32.BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);
33. 
34.// 生成透明區域爲黑色,其它區域保持不變的位圖
35.SetBkColor(hImageDC, RGB(0,0,0));
36.SetTextColor(hImageDC, RGB(255,255,255));
37.BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
38. 
39.// 透明部分保持屏幕不變,其它部分變成黑色
40.SetBkColor(hdcDest,RGB(255,255,255));
41.SetTextColor(hdcDest,RGB(0,0,0));
42.BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
43. 
44.// "或"運算,生成最終效果
45.BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);
46. 
47.// 清理、恢復   
48.SelectObject(hImageDC, hOldImageBMP);
49.DeleteDC(hImageDC);
50.SelectObject(hMaskDC, hOldMaskBMP);
51.DeleteDC(hMaskDC);
52.DeleteObject(hImageBMP);
53.DeleteObject(hMaskBMP);
54.}

2.3 TransparentBlt的另外一個版本:TransparentBltU

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

001.bool TransparentBltU(
002.HDC dcDest,         // handle to Dest DC
003.int nXOriginDest,   // x-coord of destination upper-left corner
004.int nYOriginDest,   // y-coord of destination upper-left corner
005.int nWidthDest,     // width of destination rectangle
006.int nHeightDest,    // height of destination rectangle
007.HDC dcSrc,          // handle to source DC
008.int nXOriginSrc,    // x-coord of source upper-left corner
009.int nYOriginSrc,    // y-coord of source upper-left corner
010.int nWidthSrc,      // width of source rectangle
011.int nHeightSrc,     // height of source rectangle
012.UINT crTransparent  // color to make transparent
013.)
014.{
015.if (nWidthDest < 1) return false;
016.if (nWidthSrc < 1) return false;
017.if (nHeightDest < 1) return false;
018.if (nHeightSrc < 1) return false;
019. 
020.HDC dc = CreateCompatibleDC(NULL);
021.HBITMAP bitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, GetDeviceCaps(dc,
022.BITSPIXEL), NULL);
023. 
024.if (bitmap == NULL)
025.{
026.DeleteDC(dc);   
027.return false;
028.}
029. 
030.HBITMAP oldBitmap = (HBITMAP)SelectObject(dc, bitmap);
031. 
032.if (!BitBlt(dc, 0, 0, nWidthSrc, nHeightSrc, dcSrc, nXOriginSrc,
033.nYOriginSrc, SRCCOPY))
034.{
035.SelectObject(dc, oldBitmap);
036.DeleteObject(bitmap);       
037.DeleteDC(dc);               
038.return false;
039.}
040. 
041.HDC maskDC = CreateCompatibleDC(NULL);
042.HBITMAP maskBitmap = CreateBitmap(nWidthSrc, nHeightSrc, 1, 1, NULL);
043. 
044.if (maskBitmap == NULL)
045.{
046.SelectObject(dc, oldBitmap);
047.DeleteObject(bitmap);       
048.DeleteDC(dc);               
049.DeleteDC(maskDC);           
050.return false;
051.}
052. 
053.HBITMAP oldMask =  (HBITMAP)SelectObject(maskDC, maskBitmap);
054. 
055.SetBkColor(maskDC, RGB(0,0,0));
056.SetTextColor(maskDC, RGB(255,255,255));
057.if (!BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,NULL,0,0,BLACKNESS))
058.{
059.SelectObject(maskDC, oldMask);
060.DeleteObject(maskBitmap);     
061.DeleteDC(maskDC);             
062.SelectObject(dc, oldBitmap);  
063.DeleteObject(bitmap);         
064.DeleteDC(dc);                 
065.return false;
066.}
067. 
068.SetBkColor(dc, crTransparent);
069.BitBlt(maskDC, 0,0,nWidthSrc,nHeightSrc,dc,0,0,SRCINVERT);
070. 
071.SetBkColor(dc, RGB(0,0,0));
072.SetTextColor(dc, RGB(255,255,255));
073.BitBlt(dc, 0,0,nWidthSrc,nHeightSrc,maskDC,0,0,SRCAND);
074. 
075.HDC newMaskDC = CreateCompatibleDC(NULL);
076.HBITMAP newMask;
077.newMask = CreateBitmap(nWidthDest, nHeightDest, 1,
078.GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
079. 
080.if (newMask == NULL)
081.{
082.SelectObject(dc, oldBitmap);
083.DeleteDC(dc);
084.SelectObject(maskDC, oldMask);
085.DeleteDC(maskDC);
086.DeleteDC(newMaskDC);
087.DeleteObject(bitmap);    
088.DeleteObject(maskBitmap);
089.return false;
090.}
091. 
092.SetStretchBltMode(newMaskDC, COLORONCOLOR);
093.HBITMAP oldNewMask = (HBITMAP) SelectObject(newMaskDC, newMask);
094.StretchBlt(newMaskDC, 0, 0, nWidthDest, nHeightDest, maskDC, 0, 0,
095.nWidthSrc, nHeightSrc, SRCCOPY);
096. 
097.SelectObject(maskDC, oldMask);
098.DeleteDC(maskDC);
099.DeleteObject(maskBitmap);
100. 
101.HDC newImageDC = CreateCompatibleDC(NULL);
102.HBITMAP newImage = CreateBitmap(nWidthDest, nHeightDest, 1,
103.GetDeviceCaps(newMaskDC, BITSPIXEL), NULL);
104. 
105.if (newImage == NULL)
106.{
107.SelectObject(dc, oldBitmap);
108.DeleteDC(dc);
109.DeleteDC(newMaskDC);
110.DeleteObject(bitmap);    
111.return false;
112.}
113. 
114.HBITMAP oldNewImage = (HBITMAP)SelectObject(newImageDC, newImage);
115.StretchBlt(newImageDC, 0, 0, nWidthDest, nHeightDest, dc, 0, 0, nWidthSrc,
116.nHeightSrc, SRCCOPY);
117. 
118.SelectObject(dc, oldBitmap);
119.DeleteDC(dc);
120.DeleteObject(bitmap);    
121. 
122.BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
123.newMaskDC, 0, 0, SRCAND);
124. 
125.BitBlt( dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,
126.newImageDC, 0, 0, SRCPAINT);
127. 
128.SelectObject(newImageDC, oldNewImage);
129.DeleteDC(newImageDC);
130.SelectObject(newMaskDC, oldNewMask);
131.DeleteDC(newMaskDC);
132.DeleteObject(newImage);  
133.DeleteObject(newMask);   
134. 
135.return true;
136.}

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

發佈了1 篇原創文章 · 獲贊 13 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章