这里大部分内容摘自http://www.vckbase.com/document/viewdoc/?id=532 王俊的《透明位图的显示》。自己在看程序的过程中,遇到一些问题,所以进行少量的补充和说明。
包含透明色的位图的绘制方法有多种,最简单的方法是调用现成的函数:TransparentBlt,也可以通过自己的代码实现类似TransparentBlt的功能,实现过程也有两种形式,一种是事先做一张掩码位图,另一种是动态生成掩码位图。
1、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类型
);掩码位图
原图 掩码图
2、自己的代码实现类似TransparentBlt的功能
有时候只有原图,而没有相应的掩码图,这时就要通过程序生成掩码图。
为了理解具有透明色位图的绘制过程,建立一个具有同TransparentBlt功能一致的实验函数,称之为TransparentBlt2。
实验素材:有两张位图:bk.bmp是背景位图,football.bmp包含透明区域,透明色为蓝色RGB(0,0,255)
实验目的:以bk.bmp为背景,将football.bmp绘制到背景中,形成如下的最终效果图。
2.1 透明位图绘制原理
假设football.bmp 已经载入到 HBITMAP hImageBMP中 ,hImageBMP已经选入到HDC hImageDC中
2.1.1 生成足球的单色掩码位图,透明区域为白色(全1),非透明区域为黑色(全0)
HBITMAP hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); // 建立单色位图
SetBkColor(hImageDC, RGB(0,0,255)); // 设置背景色为蓝色
为什么要设置背景色?因为hMaskBMP和hImageBMP的颜色格式是不一样的。在使用BitBlt时,会把原颜色格式转换成目标颜色格式,也就是说会把hImageBMP的彩色格式转换成单色格式(不会影响原图),再进行SRCCOPY。在这种情况下,彩色位图中所有和背景色一致的象素都变成1,其他的象素都被转换成0。
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));
为什么又要设置背景色和前景色?在将单色转换成彩色时,位为0的地方转换成目的DC的前景色,位为1的地方转换成目的DC的背景色,也就是说hMaskBMP原来的黑色区域变为RGB(255,255,255)白色,原来的白色区域变为RGB(0,0,0)黑色。再与原图相“与”。原图变成如图二所示
BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);此时hImageBMP 如下图:
(图二)
2.1.3 给背景“打洞”
SetBkColor(hdcDest,RGB(255,255,255));
SetTextColor(hdcDest,RGB(0,0,0));
同2.1.2中一样,hMaskBMP原来的黑色区域变为RGB(0,0,0)黑色,白色变为白色,就是不变。再与背景图相“与”,背景图如图三所示
BitBlt(hdcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);背景显示如下:
(图三)
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);
}
转自:http://blog.csdn.net/oeg2006/archive/2009/11/26/4877722.aspx