包含透明色的位图的绘制方法有多种,最简单的方法是调用现成的函数:TransparentBlt,也可以通过自己的代码实现类似TransparentBlt的功能,实现过程也有两种形式,一种是事先做一张掩码位图,另一种是动态生成掩码位图。本文将介绍动态生成掩码位图绘制具有透明区域位图的方法。
一、TransparentBlt 函数的使用
TransparentBlt 函数在Windows98/Windows2000以上版本运行,系统中需要包含 Msimg32.dll,使用时可以链接 Msimg32.lib。
Windows98下的TransparentBlt会产生资源泄漏,所以不建议在WIN98下使用该函数。
TransparentBlt函数原型如下:
01.BOOL TransparentBlt(02.HDC hdcDest, //
目标DC03.int nXOriginDest, //
目标X偏移04.int nYOriginDest, //
目标Y偏移05.int nWidthDest, //
目标宽度06.int hHeightDest, //
目标高度07.HDC hdcSrc, //
源DC08.int nXOriginSrc, //
源X起点09.int nYOriginSrc, //
源Y起点10.int nWidthSrc, //
源宽度11.int nHeightSrc, //
源高度12.UINT crTransparent //
透明色,COLORREF类型13.);使用示例:
1.CBitmap
FootballBMP;2.FootballBMP.LoadBitmap(IDB_FOOTBALLBMP);3.CDC
ImageDC;4.ImageDC.CreateCompatibleDC(pDC);5.CBitmap
*pOldImageBMP = ImageDC.SelectObject(&FootballBMP);6.TransparentBlt(pDC->m_hDC,
0, 0, 218, 199, ImageDC.m_hDC, 0, 0, 218, 199, RGB(0,0,0xff));7.ImageDC.SelectObject(pOldImageBMP);二、实现TransparentBlt函数
为了理解具有透明色位图的绘制过程,我们来亲手建立一个具有同TransparentBlt功能一致的实验函数,称之为TransparentBlt2。
实验素材:有两张位图:bk.bmp是背景位图,football.bmp包含透明区域,透明色为蓝色RGB(0,0,0xff)
实验目的:以bk.bmp为背景,将football.bmp绘制到背景中,形成如下的最终效果图。
2.1 透明位图绘制原理
假设football.bmp ->载入 HBITMAP hImageBMP -> 选入 HDC hImageDC
2.1.1 生成足球的单色掩码位图,透明区域为白色(全1),非透明区域为黑色(全0)
1.HBITMAP hMaskBMP
= CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); //
建立单色位图2.SetBkColor(hImageDC,
RGB(0,0,0xff)); //
设置背景色为蓝色3.BitBlt(hMaskDC,
0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY); //
拷贝到hMaskDC这样足球位图中蓝色区域在掩码位图中成了白色,其它区域为黑色,此时hMaskBMP 如下图:

(图一)
2.1.2 设置背景色为黑色,前景色为白色,将掩码位图(图一)与足球位图相"与"
1.SetBkColor(hImageDC,
RGB(0,0,0));2.SetTextColor(hImageDC,
RGB(255,255,255));3.BitBlt(hImageDC,
0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);这样,掩码位图中背景色(黑色)的区域在hImageBMP中被保留,前景色(白色)的部分变为黑色。 此时hImageBMP 如下图:

(图二)
2.1.3 设置背景色为白色,前景色为黑色,将掩码位图(图一)与背景进行“与”运算
1.SetBkColor(hdcDest,RGB(255,255,255));2.SetTextColor(hdcDest,RGB(0,0,0));3.BitBlt(hdcDest,
nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);掩码中白色区域(数据与1相“与”结果不变)使背景保持不变,黑色区域变成黑色,此时背景显示如下:

(图三)
2.1.4 将hImageBMP(图二)与背景(图三)进行“或”运算
1.BitBlt(hdcDest,
nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);这样就将足球绘制到背景上了。
2.2 TransparentBlt2函数全部实现代码
01.void TransparentBlt2( HDC hdcDest, //
目标DC02.int nXOriginDest, //
目标X偏移03.int nYOriginDest, //
目标Y偏移04.int nWidthDest, //
目标宽度05.int nHeightDest, //
目标高度06.HDC hdcSrc, //
源DC07.int nXOriginSrc, //
源X起点08.int nYOriginSrc, //
源Y起点09.int nWidthSrc, //
源宽度10.int nHeightSrc, //
源高度11.UINT crTransparent //
透明色,COLORREF类型12.)13.{14.HBITMAP hOldImageBMP,
hImageBMP = CreateCompatibleBitmap(hdcDest, nWidthDest, nHeightDest); //
创建兼容位图15.HBITMAP hOldMaskBMP,
hMaskBMP = CreateBitmap(nWidthDest, nHeightDest, 1, 1, NULL); //
创建单色掩码位图16.HDC hImageDC
= CreateCompatibleDC(hdcDest);17.HDC hMaskDC
= CreateCompatibleDC(hdcDest);18.hOldImageBMP
= (HBITMAP)SelectObject(hImageDC,
hImageBMP);19.hOldMaskBMP
= (HBITMAP)SelectObject(hMaskDC,
hMaskBMP);20. 21.//
将源DC中的位图拷贝到临时DC中22.if (nWidthDest
== nWidthSrc && nHeightDest == nHeightSrc)23.BitBlt(hImageDC,
0, 0, nWidthDest, nHeightDest, hdcSrc, nXOriginSrc, nYOriginSrc, SRCCOPY);24.else25.StretchBlt(hImageDC,
0, 0, nWidthDest, nHeightDest,26.hdcSrc,
nXOriginSrc, nYOriginSrc, nWidthSrc, nHeightSrc, SRCCOPY);27. 28.//
设置透明色29.SetBkColor(hImageDC,
crTransparent);30. 31.//
生成透明区域为白色,其它区域为黑色的掩码位图32.BitBlt(hMaskDC,
0, 0, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCCOPY);33. 34.//
生成透明区域为黑色,其它区域保持不变的位图35.SetBkColor(hImageDC,
RGB(0,0,0));36.SetTextColor(hImageDC,
RGB(255,255,255));37.BitBlt(hImageDC,
0, 0, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);38. 39.//
透明部分保持屏幕不变,其它部分变成黑色40.SetBkColor(hdcDest,RGB(255,255,255));41.SetTextColor(hdcDest,RGB(0,0,0));42.BitBlt(hdcDest,
nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hMaskDC, 0, 0, SRCAND);43. 44.//
"或"运算,生成最终效果45.BitBlt(hdcDest,
nXOriginDest, nYOriginDest, nWidthDest, nHeightDest, hImageDC, 0, 0, SRCPAINT);46. 47.//
清理、恢复 48.SelectObject(hImageDC,
hOldImageBMP);49.DeleteDC(hImageDC);50.SelectObject(hMaskDC,
hOldMaskBMP);51.DeleteDC(hMaskDC);52.DeleteObject(hImageBMP);53.DeleteObject(hMaskBMP);54.}2.3 TransparentBlt的另外一个版本:TransparentBltU
TransparentBltU是Christian Graus 在WinDEV发表的一个函数,功能与TransparentBlt一致,以下是全部实现代码:
001.bool TransparentBltU(002.HDC dcDest, //
handle to Dest DC003.int nXOriginDest, //
x-coord of destination upper-left corner004.int nYOriginDest, //
y-coord of destination upper-left corner005.int nWidthDest, //
width of destination rectangle006.int nHeightDest, //
height of destination rectangle007.HDC dcSrc, //
handle to source DC008.int nXOriginSrc, //
x-coord of source upper-left corner009.int nYOriginSrc, //
y-coord of source upper-left corner010.int nWidthSrc, //
width of source rectangle011.int nHeightSrc, //
height of source rectangle012.UINT crTransparent //
color to make transparent013.)014.{015.if (nWidthDest
< 1) return false;016.if (nWidthSrc
< 1) return false;017.if (nHeightDest
< 1) return false;018.if (nHeightSrc
< 1) return false;019. 020.HDC dc
= CreateCompatibleDC(NULL);021.HBITMAP bitmap
= CreateBitmap(nWidthSrc, nHeightSrc, 1, GetDeviceCaps(dc,022.BITSPIXEL),
NULL);023. 024.if (bitmap
== NULL)025.{026.DeleteDC(dc); 027.return false;028.}029. 030.HBITMAP oldBitmap
= (HBITMAP)SelectObject(dc,
bitmap);031. 032.if (!BitBlt(dc,
0, 0, nWidthSrc, nHeightSrc, dcSrc, nXOriginSrc,033.nYOriginSrc,
SRCCOPY))034.{035.SelectObject(dc,
oldBitmap);036.DeleteObject(bitmap); 037.DeleteDC(dc); 038.return false;039.}040. 041.HDC maskDC
= CreateCompatibleDC(NULL);042.HBITMAP maskBitmap
= CreateBitmap(nWidthSrc, nHeightSrc, 1, 1, NULL);043. 044.if (maskBitmap
== NULL)045.{046.SelectObject(dc,
oldBitmap);047.DeleteObject(bitmap); 048.DeleteDC(dc); 049.DeleteDC(maskDC); 050.return false;051.}052. 053.HBITMAP oldMask
= (HBITMAP)SelectObject(maskDC,
maskBitmap);054. 055.SetBkColor(maskDC,
RGB(0,0,0));056.SetTextColor(maskDC,
RGB(255,255,255));057.if (!BitBlt(maskDC,
0,0,nWidthSrc,nHeightSrc,NULL,0,0,BLACKNESS))058.{059.SelectObject(maskDC,
oldMask);060.DeleteObject(maskBitmap); 061.DeleteDC(maskDC); 062.SelectObject(dc,
oldBitmap); 063.DeleteObject(bitmap); 064.DeleteDC(dc); 065.return false;066.}067. 068.SetBkColor(dc,
crTransparent);069.BitBlt(maskDC,
0,0,nWidthSrc,nHeightSrc,dc,0,0,SRCINVERT);070. 071.SetBkColor(dc,
RGB(0,0,0));072.SetTextColor(dc,
RGB(255,255,255));073.BitBlt(dc,
0,0,nWidthSrc,nHeightSrc,maskDC,0,0,SRCAND);074. 075.HDC newMaskDC
= CreateCompatibleDC(NULL);076.HBITMAP newMask;077.newMask
= CreateBitmap(nWidthDest, nHeightDest, 1,078.GetDeviceCaps(newMaskDC,
BITSPIXEL), NULL);079. 080.if (newMask
== NULL)081.{082.SelectObject(dc,
oldBitmap);083.DeleteDC(dc);084.SelectObject(maskDC,
oldMask);085.DeleteDC(maskDC);086.DeleteDC(newMaskDC);087.DeleteObject(bitmap); 088.DeleteObject(maskBitmap);089.return false;090.}091. 092.SetStretchBltMode(newMaskDC,
COLORONCOLOR);093.HBITMAP oldNewMask
= (HBITMAP)
SelectObject(newMaskDC, newMask);094.StretchBlt(newMaskDC,
0, 0, nWidthDest, nHeightDest, maskDC, 0, 0,095.nWidthSrc,
nHeightSrc, SRCCOPY);096. 097.SelectObject(maskDC,
oldMask);098.DeleteDC(maskDC);099.DeleteObject(maskBitmap);100. 101.HDC newImageDC
= CreateCompatibleDC(NULL);102.HBITMAP newImage
= CreateBitmap(nWidthDest, nHeightDest, 1,103.GetDeviceCaps(newMaskDC,
BITSPIXEL), NULL);104. 105.if (newImage
== NULL)106.{107.SelectObject(dc,
oldBitmap);108.DeleteDC(dc);109.DeleteDC(newMaskDC);110.DeleteObject(bitmap); 111.return false;112.}113. 114.HBITMAP oldNewImage
= (HBITMAP)SelectObject(newImageDC,
newImage);115.StretchBlt(newImageDC,
0, 0, nWidthDest, nHeightDest, dc, 0, 0, nWidthSrc,116.nHeightSrc,
SRCCOPY);117. 118.SelectObject(dc,
oldBitmap);119.DeleteDC(dc);120.DeleteObject(bitmap); 121. 122.BitBlt(
dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,123.newMaskDC,
0, 0, SRCAND);124. 125.BitBlt(
dcDest, nXOriginDest, nYOriginDest, nWidthDest, nHeightDest,126.newImageDC,
0, 0, SRCPAINT);127. 128.SelectObject(newImageDC,
oldNewImage);129.DeleteDC(newImageDC);130.SelectObject(newMaskDC,
oldNewMask);131.DeleteDC(newMaskDC);132.DeleteObject(newImage); 133.DeleteObject(newMask); 134. 135.return true;136.}说明:本文提供的TransparentBlt2函数旨在说明透明位图的显示原理,在Windows2000以上环境实际运用中建议使用现成的TransparentBlt函数来绘制透明位图。
1035

被折叠的 条评论
为什么被折叠?



