博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VC——位图的透明显示
阅读量:3976 次
发布时间:2019-05-24

本文共 4011 字,大约阅读时间需要 13 分钟。

这里大部分内容摘自 王俊的《透明位图的显示》。自己在看程序的过程中,遇到一些问题,所以进行少量的补充和说明。

包含透明色的位图的绘制方法有多种,最简单的方法是调用现成的函数: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://nieki.baihongyu.com/

你可能感兴趣的文章
字符转译序列
查看>>
Java 数据类型
查看>>
UTF-16 编码简介
查看>>
Java 变量名
查看>>
Java 四舍五入运算
查看>>
Spring Batch 例子: 运行系统命令
查看>>
Spring Batch 核心概念
查看>>
Spring Batch 例子: 导入定长文件到数据库
查看>>
正则表达式
查看>>
Java I/O
查看>>
序列化
查看>>
Perl 精萃
查看>>
数据类型之列表与数组
查看>>
XStream 环境设置
查看>>
Git 分支
查看>>
Git 冲突
查看>>
Git Merging vs. Rebasing
查看>>
libreoffice/openoffice c/c++转换office格式为pdf
查看>>
Tomcat 7.0 64位免安装解压版 安装及配置
查看>>
Android 网络编程 初级入门(一)
查看>>