轉自: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函數來繪製透明位圖。