VC++实现位图显示透明效果

来源:互联网 发布:淘宝联盟加油升级 编辑:程序博客网 时间:2024/06/05 19:45
我们在进行程序的界面设计时,常常希望将位图的关键部分,也既是图像的前景显示在界面上,而将位图的背景隐藏起来,将位图与界面很自然的融合在一起,本文介绍了透明位图的制作知识,并将透明位图在一个对话框中显示了出来。本文所使用的原始位图及程序编译运行后的界面效果如下图所示:

图一、原始位图

图二、对话框界面上透明显示位图

  一、实现方法

  绘制"透明"位图是指绘制某一位图中除指定颜色外的其余部分,我们称这种颜色为"透明色"。通过将位图的背景色指定为"透明色",在绘制时,不绘制这部分背景,而仅绘制图像,这样就可以将位图中图像透明地绘制到窗口上。

  绘制"透明"位图的关键是创建一个"掩码"位图(mask bitmap),"掩码"位图是一个单色位图,它是位图中图像的一个单色剪影。在Windows编程中,绘图都要用到设备描述表,我们需创建两个内存设备描述表:位图设备描述表(image DC)和"掩码"位图设备描述表(mask DC)。位图设备描述表用来装入位图,而"掩码"位图设备描述表用来装入"掩码"位图。在"掩码"位图设备描述表中制作"掩码"位图的方式是:先创建一个单色的Bitmap,装入mask DC,然后,以"SRCCOPY"的方式将装有位图的位图设备描述表绘制(BitBlt)到mask DC上。这样,mask DC的显示平面中的位图即是"掩码"位图。

       一般情况下,绘制"透明"位图的实际操作步骤如下:

  1、甚至待显示位图的背景颜色,也就是设置我们希望透明显示的位图颜色;

  2、位图设备描述表以"SRCINVERT"的方式绘制(BitBlt)到显示设备描述表上;

  3、"掩码"位图设备描述表以"SRCAND"的方式绘制(BitBlt)到显示设备描述表上;

  4、再将位图设备描述表以"SRCINVERT"的方式绘制(BitBlt)到显示设备描述表上。这样除"透明色"外的其余位图部分(图像部分)就被绘制到窗口上了。

  上述操作中需要用到的位图显示函数BitBlt()的原型和说明如下:

BOOL BitBlt( int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc,
int ySrc, DWORD dwRop );

  其中,参数int x表示贴到目的地的左上角X坐标;int y表示/贴到目的地的左上角Y坐标;int nWidth表示贴到目的地的区域宽度;int nHeight表示贴到目的地的区域高度;CDC* pSrcDC表示存储源位图的设备描述表;int xSrc表示源位图的左上角X坐标;int ySrc表示源位图的左上角Y坐标;DWORD dwRop为柵格运算标志(ROP),它明确定义了如何将源文件、目标文件和模式(由现在选出的刷子画笔定义)的位组合去形成一个目标文件。对于所有的设备类型,光栅操作(ROP)只简单地在表示位图颜色的每一个bit位上展开相关操作而不考虑他们的实际意义。微软为位图的光栅操作提供了多种方法,开发人员可以使用不同的组合得到想要的特殊效果。由于篇幅的限制,本文只讨论四种常用的光栅操作:

操作方式运算方式效果
SRCCOPYsrc 直接将源位图拷贝到目的设备上。
SRCAND src AND dest将目标文件中对应于源文件黑色区域的部分变黑,将对应于白色区域的部分留着不动。
SRCINVERT src XOR dest 将源插入到目标。二次使用时,将目标恢复到它原来的状态。在某种条件下可以代替SRCPAINT 操作。
SRCPAINTsrc OR dest将源文件中的白色区域刷到目标文件中。源中的黑色区域不转换到目标中。

  这里补充说明一点,显示位图的背景颜色可以通过PhotoShop等图像处理软件获取,当然,也可以通过读取位图上特殊位置上的像素点的颜色来获取,前者实现起来比较方便,后者稍微麻烦一些,这可以根据个人爱好自由选择。

 

     二、示例程序

  首先启动Visual C++6.0,生成一个基于对话框架的应用程序,将程序命名为"TransPrarentImage";然后添加位图资源,其ID为IDB_DRAGON,在void CTransPrarentImageDlg::OnPaint() 后面中加入如下代码

 //transparent
 CDC * pDC=GetDC();
 CDC dcImage,dcTrans;


 CBitmap dragon;
 dragon.LoadBitmap(IDB_DRAGON);
 BITMAP bm;
 dragon.GetBitmap(&bm);
 int nWidth=bm.bmWidth;
 int nHight=bm.bmHeight;


 dcImage.CreateCompatibleDC(pDC);
 dcTrans.CreateCompatibleDC(pDC);
 
 CBitmap *pOldBitmapImage=dcImage.SelectObject(&dragon);
 CBitmap bitmapTrans;
 bitmapTrans.CreateBitmap(nWidth,nHight,1,1,NULL);
 CBitmap *pOldBitmapTrans=dcTrans.SelectObject(&bitmapTrans);
 
 dcImage.SetBkColor(RGB(255,0,255));

 //如果想要背景是黑色的话则为dcImage.SetBkColor(RGB(0,0,0));
 dcTrans.BitBlt(0,0,nWidth,nHight,&dcImage,0,0,SRCCOPY);
 pDC->BitBlt(0,0,nWidth,nHight,&dcImage,0,0,SRCINVERT);
 pDC->BitBlt(0,0,nWidth,nHight,&dcTrans,0,0,SRCAND);
 pDC->BitBlt(0,0,nWidth,nHight,&dcImage,0,0,SRCINVERT);

 

  三、小结

  本实例介绍了如何通过简单的方法在对话框中实现透明位图的显示,读者朋友可以从中开拓思路,实现更多的特殊显示效果。

可以写成一个函数:

void Cxxxxx::DrawTransparent(CDC * pDC, int x, int y, COLORREF crColour)
{
COLORREF crOldBack = pDC->SetBkColor(m_crWhite);
COLORREF crOldText = pDC->SetTextColor(m_crBlack);
CDC dcImage, dcTrans;

// Create two memory dcs for the image and the mask
dcImage.CreateCompatibleDC(pDC);
dcTrans.CreateCompatibleDC(pDC);

// Select the image into the appropriate dc
CBitmap* pOldBitmapImage = dcImage.SelectObject(this);

// Create the mask bitmap
CBitmap bitmapTrans;
 BITMAP bm; 
 bitmapTrans.GetBitmap(&bm);
 int nWidth=bm.bmWidth;
 int nHight=bm.bmHeight;

 bitmapTrans.CreateBitmap(nWidth, nHeight, 1, 1, NULL);

// Select the mask bitmap into the appropriate dc
CBitmap* pOldBitmapTrans = dcTrans.SelectObject(&bitmapTrans);

// Build mask based on transparent colour
dcImage.SetBkColor(crColour);
dcTrans.BitBlt(0, 0, nWidth, nHeight, &dcImage, 0, 0, SRCCOPY);

// Do the work - True Mask method - cool if not actual display
pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);
pDC->BitBlt(x, y, nWidth, nHeight, &dcTrans, 0, 0, SRCAND);
pDC->BitBlt(x, y, nWidth, nHeight, &dcImage, 0, 0, SRCINVERT);

// Restore settings
dcImage.SelectObject(pOldBitmapImage);
dcTrans.SelectObject(pOldBitmapTrans);
pDC->SetBkColor(crOldBack);
pDC->SetTextColor(crOldText);
}

原创粉丝点击