透明位图显示

包含透明色的位图的绘制方法有多种,最简单的方法是调用现成的函数: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
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值