http://www.vckbase.com/document/viewdoc/?id=532
在上面的链接有篇文章,介绍透明位图的显示,其中一个数: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(0xff,0xff,0xff));
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);

}其中:// 生成透明区域为白色,其它区域为黑色的掩码位图
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);这句为什么可以把透明区域变为黑色,其它区域保持不变的位图?任何数与0相“与”,应该结果都是零的啊,是不是两个SetBkColor和SetTextColor起了作用,为什么呢,谁可以详细解释一下?

解决方案 »

  1.   

    透明图原理:
    首先准备一张蒙板(想画的区域为纯黑,背景纯白),一张源图(背景纯黑)
    首先用mask与当前dc中存放的图(以下称作背景图,就是已经画上去的图)‘与’
    BitBlt(mdc, 0, 0, nWidthDest, nHeightDest, m_bufdc[L_MASK], 0, 0, SRCAND);
    注意对于图片来说,只有纯黑RGB(0,0,0)为0,其余即使是RGB(0,0,1)也是1
    所以背景图‘与’蒙板,
    ((0或1)与 0 = 0)故蒙板为黑的地方背景图为黑
    ((0或1)与 非0 = 非0,不变)故蒙板为非0(即1)的地方背景图不变BitBlt(mdc, 0, 0, nWidthDest, nHeightDest, m_bufdc[L_SOURCE], 0, 0, SRCPAINT);
    同理,之后背景图再‘或’源图
    (0(蒙板蒙上的地方)或 非0 = 非0)故背景图被蒙板蒙上的黑色区域被画上源图
    ((0或1)或 0 = (0或1,不变))故背景图没有被蒙板蒙上的其他区域不变是不是很像绕口令?呵呵其实只要记住红色的那句话就可以了!
      

  2.   

    等等,没完,以下是重点:    
    // 设置透明色
        SetBkColor(hImageDC, crTransparent);//这很重要,下面会讲到
        
    // 生成透明区域为白色,其它区域为黑色的掩码位图
    //注意这里的关键在于
    //之前的这两句:
    //HBITMAP hOldMaskBMP, hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL);            // 创建单色掩码位图
    //hOldMaskBMP = (HBITMAP)SelectObject(hMaskDC, hMaskBMP);
    //由于hMaskDC关联的位图是单色的,所以以下这一句:    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);
       
    //Bitblt会将其hImageDC关联的彩色位图画入hMaskDC并且转换成单色,如此一来就必须符合
    //彩色-单色位图转换原理
    //彩色位图白色(1)-> 单色位图白色(1)
    //彩色位图非白色(非1)-> 单色位图黑色(0) 
    //
    由此可知只要传入的hImageDC关联的位图背景是白色或者透明(这就是之前设置背景透明的原因),//那么这句Bitblt就将自动生成符合要求的蒙板。
    ----------------------------------------------------------------------------------------
    // 生成透明区域为黑色,其它区域保持不变的位图
        SetBkColor(hImageDC, RGB(0,0,0));//这句将原来是透明的背景变成了纯黑,所以现在,hImageDC的背景//成为纯黑
        SetTextColor(hImageDC, RGB(255,255,255));//设置字体的,it doesn't matter.
    //此时hMaskDC关联的位图是单色,而hImageDC关联的位图是彩色,所以这里Bitblt会再将hMaskDC关联的位图视//为彩色,AND操作后hImageDC关联的位图成为黑色背景的标准源位图
        BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
    ------------------------------------------------------------------------------------------
    说实话写这代码的人实在生猛,已经把镂空图理解到了极致,佩服。但是话说我并不喜欢这种做法,麻烦。
    我比较喜欢这样:
    m_Source=(HBITMAP)LoadImage(NULL, "X:\Source.bmp",IMAGE_BITMAP, width,height, LR_LOADFROMFILE);
    m_Mask=(HBITMAP)LoadImage(NULL, "X:\Mask.bmp",IMAGE_BITMAP, width,height, LR_LOADFROMFILE);
    在外边就先用Photoshop或者Windows画图把源位图和蒙板处理好在用,这样用的时候直接两个BitBlt就完美镂空了,而且不要像你这个BT的代码这么转换来转换去的,方便简单快捷好用,何乐不为?
      

  3.   

    还是不明白:
    //彩色-单色位图转换原理
    //彩色位图白色(1)-> 单色位图白色(1)
    //彩色位图非白色(非1)-> 单色位图黑色(0
    例子中是把背景设为蓝色,而不是白色,蓝色->单色会是黑色啊?// 生成透明区域为黑色,其它区域保持不变的位图
      SetBkColor(hImageDC, RGB(0,0,0));//这句将原来是透明的背景变成了纯黑,所以现在,hImageDC的背景//成为纯黑
      SetTextColor(hImageDC, RGB(255,255,255));//设置字体的,it doesn't matter.
    //此时hMaskDC关联的位图是单色,而hImageDC关联的位图是彩色,所以这里Bitblt会再将hMaskDC关联的位图视//为彩色,AND操作后hImageDC关联的位图成为黑色背景的标准源位图
      BitBlt(hImageDC, 0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);
    不太明白“Bitblt会再将hMaskDC关联的位图视为彩色”是什么意思。hMaskDC中的白色与hImageDC中的黑色相“与”等于黑色,hMaskDC中的黑色与hImageDC中的前景色白色“与”还是黑色啊。
    前景色与背景色到底是指哪里的颜色?
      

  4.   

    对于SetTextColor和SetBkColor到底是什么作用就知道了,百度过,很多人说的很模糊。工作上有个地方用到类似的代码,当时也看了看这篇TransparentBlt的原理,没懂...
      

  5.   

    过后试了一下我发现我在4楼的回答漏洞百出,在此表示道歉,并且更正。真切的希望以后看到此贴的人将4楼加以无视现在回答你9L的问题
    1.
    ASK1:
    例子中是把背景设为蓝色,而不是白色,蓝色->单色会是黑色啊?
    ANSWER1:
    先看代码:这一句// 生成透明区域为白色,其它区域为黑色的掩码位图
    BitBlt(hMaskDC, 0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);如前边说过的,由于hMaskDC关联的位图是单色的,所以这里Bitble内部将自动把hImageDC关联的彩色位图转换成单色位图,以匹配hMaskDC;
    在此之前调用了重要的SetBkColor:// 设置透明色
    SetBkColor(hImageDC, crTransparent);至于为什么要调用SetBkColor,MSDN给的解释是这样的:
    (见SetBkColor函数的Re)
    The background color is also used when converting bitmaps from color to monochrome and vice versa. 就是说此函数在单色位图&彩色位图互相转换的时候将会起作用,可以推断在这里的作用是将背景色转换为了白色,非背景色转换成了黑色。(和之前所说的彩色-单色位图转换原理没什么关系,我说错了)
    你问的为什么背景是蓝色也可以转换成白色,就是因为我们用SetBkColor将背景色设置成了蓝色,如果我没猜错的话,那个crTransparent参数,你所传入的就是蓝色。ASK2:
    不太明白“Bitblt会再将hMaskDC关联的位图视为彩色”是什么意思。hMaskDC中的白色与hImageDC中的黑色相“与”等于黑色,hMaskDC中的黑色与hImageDC中的前景色白色“与”还是黑色啊。
    前景色与背景色到底是指哪里的颜色?
    ANSWER2:
    同样,第二个问题中的这一句:
    //SetTextColor(hImageDC, RGB(255,255,255));
    在MSDN的SetTextColor函数Re中也有如下一段话:
    The text color is also used in converting bitmaps from color to monochrome and vice versa. 
    此函数在单色位图&彩色位图互相转换的时候也将起作用,可以推断SetBkColor设置的是背景色,而SetTextColor设置的是前景色。(我之前顾名思意以为它是设置字体用了,又说错了。)
    至于你问的
    “hMaskDC中的白色与hImageDC中的黑色相“与”等于黑色,hMaskDC中的黑色与hImageDC中的前景色白色“与”还是黑色”
    很遗憾这可是Bitblt函数的内部机制。谁叫Microsoft不开源呢?所以没能进MS Corporation的不知道其中机制,进了MS的又签了保密协议守口如瓶,我们能做的就只能是推断函数的机制,同时照着MSDN使用而已。
    你的这段代码应该就是MSDN的例子吧?如果哪天楼主进了MS Corp,可别忘了把这函数的源代码Copy一份给在下啊。不过楼主要是真想深研的话,我推荐你去看看wxWidget库,这个库和Windows的MFC十分类似,也是用SDK为基础写的(如果你想要SDK的源代码,那你还是去hack微软吧,谁叫我们用的是Windows呢?不开源。或者换用Linux)。这个库是开源的,wxWidget里面的函数dc类的Blit就是效仿MS Windows的dc类的Bitblt写的,这个函数中也使用SetTextColor,SetBkColor&Bitblt三个API实现了透明图效果,反正我是看不懂,你要是需要也可以留下邮箱我发给你。