1、- 1 -透明贴图绘制透明位图是指在绘制位图时只绘制除了指定颜色外的其余部分,而指定的颜色就被称为“透明色” 。通过将位图的背景色指定成“透明色” ,在绘制时不绘制带“ 透明色”的这部分背景,仅绘制图像,这样就可以将图像透明地绘制到窗口上。绘制包含透明色的位图的方法有许多种,比较常用的是屏蔽绘制和非屏蔽绘制,屏蔽绘制指的是事先做一张掩码位图,非屏蔽绘制是动态生成掩码位图。下面将分别详细介绍这两种绘制方法。在写透明贴图的方法前先来说说透明贴图,所谓的透明贴图并不是真正意义上的透明,而是图像不需要显示的部分显示出的颜色是当前对话框的背景色,也就是说把图像不需要显示的颜色当成背景色,显示的部分作为前
2、景色,透明就是把背景换成对话框背景。要实现这种透明有两种方法,一种是让背景色成为白色,然后与对话框背景色进行与运算;还有一种是让背景色成为黑色,然后与对话框背景色进行或运算。这样位图的背景色就消失了。了解了透明的概念,就可以避免透明贴图的一些缺点,如果位图的前景色也存在许多白色,则采用将背景色变成黑色,与对话框背景色进行或运算的方法,这样前景色的白色部分才不会被误当成背景色透明显示;反过来,如果位图前景色存在大量黑色部分是,则采用将背景色变成白色,与对话框背景色进行与运算的方法。当然,如果前景色同时存在大量白色和黑色时,则透明贴图会遇到大麻烦,需要想办法将位图的白色或黑色部分做一些修改后再进行
3、透明贴图。屏蔽绘制绘制透明位图的关键就是创建一个“掩码” 位图(mask bitmap),这个“掩码”位图是一个单色位图,它是位图中图像的一个单色剪影。在 MFC 中,绘图需要使用设备描述表,透明贴图时需要创建两个内存设备描述表,一个是用于存放位图的设备描述表(imgDC),一个是用于存放“掩码” 位图的设备描述表(maskDC)。在 “掩码”位图设备描述表中制作“掩码” 位图的方法是先创建一个单色的bitmap,放入掩码设备描述表(maskDC)中,然后使用拷贝粘贴的方式将存放有位图的设备描述表(imgDC)绘制到掩码设备描述表上,这样,掩码设备描述表显示的位图即是“掩码” 位图。在详细介绍
4、实现过程之前先介绍下所使用的画图函数以及函数参数所代表的功能;整个绘制过程需要使用到 BitBlt()函数,关于这个函数,MSDN 上的说明是这样的:这个函数的功能是把源设备上下文中的一个矩形区域中所有像素的颜色比特信息传输给目标设备上下文。BOOL BitBlt(int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop);函数参数如下:Int x 表示绘制位图目标左上角 x 坐标;- 2 -Int y 表示绘制位图目标左上角 y 坐标;Int nWidth 表示绘制位图目标的区域宽度
5、;Int nHeight 表示绘制位图目标的区域高度;CDC* pSrcDC 表示存储源位图的设备描述表;Int xSrc 表示源位图的左上角 x 坐标;Int ySrc 表示源位图的左上角 y 坐标;DWORD dwRop 表示栅格运算标志;dwRop 的取值与值的描述如下表所示:值 描述BLACKNESS 用调色板中索引为 0 的颜色( 默认是黑色)填充目标矩形。CAPTUREBLT 用调色板中索引为 0 的颜色( 默认是黑色)填充目标矩形。DSTINVERT 将目标矩形反色。MERGECOPY 将源矩形中的颜色与当前目标设备环境选中的画刷通过逻辑与操作进行混合。MERGEPAINT 将源
6、矩形的颜色反色后与目标矩形的颜色通过逻辑或操作进行混合。NOMIRRORBITMAP 防止位图镜像翻转。NOTSRCCOPY 源矩形反色复制到目标矩形。NOTSRCERASE 将源矩形与目标矩形的颜色通过逻辑或操作混合后,再反色。PATCOPY 将目标设备环境选中的画刷复制到目标位图。PATINVERT 将目标设备环境选中的画刷与目标矩形中的颜色进行逻辑异或操作,复制到目标位图。PATPAINT 将目标设备环境选中的画刷与源矩形中的颜色的反色进行逻辑或操作,其结果再与目标矩形的颜色进行逻辑或操作。SRCAND 将源矩形与目标矩形的颜色进行逻辑与操作。SRCCOPY 直接将源矩形拷贝到目标矩形,
7、最常用的绘制位图属性。SRCERASE 将目标矩形的反色与源矩形的颜色进行逻辑与操作。SRCINVERT 将源矩形的颜色与目标矩形进行逻辑异或操作。SRCPAINT 将源矩形的颜色与目标矩形进行逻辑或操作。WHITENESS 用调色板中索引为 1 的颜色( 默认是白色)填充目标矩形。原图如下所示,- 3 -下面是整个实现过程:1) 创建一张大小与需要绘制图像相同的位图作为“ 掩码”位图;2) 将新创建的“掩码” 位图存储至掩码位图的设备描述表中;3) 把位图设备描述表的背景设置成“ 透明色”,即不需要显示的颜色;4) 复制粘贴位图到“掩码” 位图的设备描述表中,这个时候 “掩码”位图设备描述表
8、中存放的位图与位图设备描述表中的位图一样;5) 把需要透明绘制的位图与对话框绘图相应区域的背景进行逻辑异或操作绘制到对话框上;结果如下图所示,- 4 -6) 把“掩码 ”位图与这个时候对话框相应区域的背景进行逻辑与的操作;结果如下图所示,- 5 -这个时候显示出来的对话框背景就是需要绘制透明位图的剪影了;7) 最后一步重复步骤 5 的操作,把需要透明绘制的位图与对话框绘图相应区域的背景进行逻辑异或操作绘制到对话框上;结果如下图所示,- 6 -这个时候大功告成,位图已经透明地显示在了对话框中;8) 当然最后不要忘记了把系统的画笔还给系统,删除使用过的 GDIObject,释放非空的指针,最后把新
9、建的设备描述表也删除;具体代码如下显示,这段代码只是截取了在 WM_PAINT 消息中对话框客户区画图的部分,位图的加载和删除分别写在 OnInitDialog()函数和析构函数中;CDC imgDC, maskDC; /定义存储位图的位图设备描述表imgDC和存储掩码位图的掩码位图/设备描述表maskDCCRect rcWnd, rcPic;imgDC.CreateCompatibleDC(NULL); /初始化设备描述表maskDC.CreateCompatibleDC(NULL); /初始化设备描述表CBitmap bmpMask;BITMAP bm;m_bmpSample.GetBit
10、map(GetClientRect(rcWnd);- 7 -rcPic.left = (rcWnd.Width() - bm.bmWidth)/2;rcPic.right = rcPic.left + bm.bmWidth;rcPic.top = (rcWnd.Height() - bm.bmHeight)/2;rcPic.bottom = rcPic.top + bm.bmHeight;bmpMask.CreateBitmap(bm.bmWidth, bm.bmHeight, 1, 1, NULL); /初始化掩码位图CBitmap * pOldBmp = imgDC.SelectObjec
11、t( /存储位图至位图设备描述表CBitmap * pOldMaskBmp = maskDC.SelectObject( /存储掩码位图至掩码位图/设备描述表imgDC.SetBkColor(RGB(255, 255, 0); /设置位图设备描述表的背景色为透明色maskDC.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, dc.BitBlt(rcPic.left, rcPic.top, bm.bmWidth, bm.bmHeight, dc.BitBlt(rcPic.left, rcPic.top, bm.bmWidth, bm.bmHeight, dc.BitB
12、lt(rcPic.left, rcPic.top, bm.bmWidth, bm.bmHeight, imgDC.SelectObject(pOldBmp);maskDC.SelectObject(pOldMaskBmp);bmpMask.DeleteObject();pOldBmp = NULL;pOldMaskBmp = NULL;DeleteDC(imgDC);DeleteDC(maskDC);非屏蔽绘制说到非屏蔽绘制透明贴图就是动态生成掩码位图,最常用的方法就是 TransparentBlt()函数,关于这个函数 MSDN 上是这样描述的:TransparentBlt()函数从指定源设
13、备上下文中的矩形区域中像素的色彩信息转化为目标设备上下文中。TransparentBlt()函数在 Windows98/Windows2000 以上版本运行,系统中需要包含 Msimg32.dll,使用时可以链接 Msimg32.lib。Windows98 下的 TransparentBlt()会产生资源泄漏,所以不建议在 WIN98 下使用该函数。TransparentBlt()函数原型如下: BOOL TransparentBlt(HDC hdcDest, /目标 DCint nXOriginDest, /目标 X 偏移- 8 -int nYOriginDest, /目标 Y 偏移int nWidthDest, /目标宽度int hHeightDest, /目标高度HDC hdcSrc, /源 DCint nXOriginSrc, /源 X 起点int nYOriginSrc, /源 Y 起点int nWidthSrc, /源宽度int nHeightSrc, /源高度UINT crTransparent /透明色,COLORREF 类型);