http://express.ruanko.com/ruanko-express_17/webpage/tech3.html
这里写的真不错,要好好看几遍,对DC认识的不清,对BitBlt认识不清的人可以收获不少。特别是结合光栅操作码看。
但是对中间掩码位图的由来不清楚,怎么样制作掩码位图呢?
http://www.pcdog.com/a/19/10/x211415.html
又发现了上面的这个地方,讲到如何一幅位图的掩码位图,正合我意。主要用到了CreateBitmap()创建了一幅单色的位
图,然后将装有源位图的设备描述表的背景色设为源位图的背景色——蓝色,然后将装有源位图的设备描述表的内容复
制到装有源码位图的设备描述表中,这时掩码位图成了图一,我感觉这里的hMaskDC还要把hMaskBMP装进去才行,这里
应该是漏掉了。
http://www.518it.net/html/pxjc/2009/0717/762.html
这里也讲到了“"掩码"位图的方式是:先创建一个单色的Bitmap,装入mask DC,然后,以"SRCCOPY"的方式将装有位图
的位图设备描述表绘制(BitBlt)到mask DC上。这样,mask DC的显示平面中的位图即是"掩码"位图。”
知道了掩码位图的制作过程,也算小有收获。
不过后面讲的一会“设置背景色为黑色,前景色为白色,将掩码位图(图一)与足球位图相"与"”,一会“设置背景色为
白色,前景色为黑色,将掩码位图(图一)与背景进行“与”运算”倒是把我弄糊涂了。
糊涂了良久,请教了师兄,之前也是有些糊涂,对设置前景色与背景色,然后在结合光栅操作码这一做法十分不理解,如果说把生成掩码位图的方式说成是一种规定,那么与后面的“规定”似乎有矛盾的地方。
还好师兄百度了一下,找到:
http://blog.sina.com.cn/s/blog_4e6f376d01000b8p.html
中间有一个关键的地方,那就是单色位图与彩图之间的转换的问题。
模拟透明的方法也包含基于windows的单色图向彩色图转换的机制,反之亦然。Windows概念中的文本颜色(前景色)和
背景色被用来映射两种格式的转换。在blt操作中,当dest为彩色图,src为单色图时,在进行ROP(SRCAND,SRCAND,
SRCINVERT,SRCPAINT等),操作之前,单色图src中的0(black)像素被转换成dest的前景色,1(white)像素被转化
为dest的背景色。相反,从彩色图向单色图转换时,即dest为单色图,src为彩色图时,src彩色图中所有与其背景颜色
相同的像素变成1,与其背景不同的变为0。
这是问题的关键点,有了这一点说明,之前的设置设备前景色与背景色的不解就消失了。这里还对前景色和背景色是“
映射两种格式的转换”,之前对前景色和背景色的错误认识也得到纠正。以后还是要换角度百度。
自己准备编一个程序试一试。
http://www.pcdog.com/a/19/10/x211415.html
先参照上述源码,利用现成的::TransparentBlt或者TransparentBlt2实现最简单的功能。
首先新建一基于对话框的工程testtransparent,然后需要载入那两幅图片进工程,本来准备用抓图软件在网页上抓的,
但是后来看到源码的工程中有现成的,也省了点事。将图片的ID改为IDB_BKBMP,IDB_FOOTBALLBMP,然后在
CTesttransparentDlg::OnPaint()的else{}中添加:
CBitmap m_bmpBackground;
CBitmap m_bmpFootball;
m_bmpBackground.LoadBitmap(IDB_BKBMP);
m_bmpFootball.LoadBitmap(IDB_FOOTBALLBMP);
CDialog::OnPaint();
COLORREF crMask = RGB(0x00,0x00,0xff);
BITMAP bm;
m_bmpFootball.GetBitmap(&bm);
int nWidth = bm.bmWidth;
int nHeight = bm.bmHeight;
CDC ImageDC;
ImageDC.CreateCompatibleDC(&dc);
CBitmap *pOldImageBMP = ImageDC.SelectObject(&m_bmpFootball);
::TransparentBlt(dc.m_hDC,50,40,nWidth,nHeight,ImageDC.m_hDC,0,0,nWidth,nHeight,crMask);
//TransparentBlt2
(dc.m_hDC,50,40,nWidth,nHeight,ImageDC.m_hDC,0,0,nWidth,nHeight,crMask);
ImageDC.SelectObject(pOldImageBMP);
好了,应该可以看到效果了。编译,发现dc非法,一看,原来CPaintDC dc(this);出现在了OnPaint()的if语句内了,
将其拿到if语句的顶上就可以了。一编译,无错,连接,有错,提示外来符号TransparentBlt有问题。哦,网页中提到
要用这个现成的函数需要添加一个函数库。比较了一下两个工程的.cpp文件,发现少了#pragma comment( lib,
"Msimg32.lib" )。加上,编译连接无错,运行,效果达到。注释::TransparentBlt行,启用TransparentBlt2,效果也
达到。当然要启用TransparentBlt2必须要在.cpp找个空处添加函数的实现。
好了,下面准备在OnPaint中直接实现TransparentBlt2的功能。写了一下,还有些问题,如果时间多的话,调出来应该没问题,可恶的是一大堆的烦心事要做。暂且阁下吧。
还有当前打开的一些网页,有时间也要看看,先留下。
http://www.518it.net/html/pxjc/2009/0717/762_2.html
http://express.ruanko.com/ruanko-express_17/webpage/tech3.html
http://www.zjol.com.cn/node2/node195/node56935/node56938/userobject7ai24982.html
http://tech.sina.com.cn/s/2005-08-09/0849686941.shtml
http://hi.baidu.com/soulshape/blog/item/897286129f0facc5c2fd7805.html
上述最后一个降到了HBITMAP和CBitmap转换的问题,我要是按照前面讲的制作掩码位图的方法做,这个转换还必须要用到。
总结一下,该功能的实现要注意几个关键点,一是对设备描述表,或者说设备环境,或者说设备场景要理解透彻,二是对BitBlt这个函数要认识清楚,三是要知道用BitBlt时存在一个单色位图和彩色位图之间的转换规定。
转自:http://sxjj04.blog.163.com/blog/static/122592653201051711262462/