WINCE 下实现类TransparenBlt 的BMP 透明色显示功能

最近在WINCE上面搭建MFC应用,本来一般的图形显示还好,但是当我想实现BMP的边框透明效果的时候却不行了。因为在WINDOWS上是有TransparentBlt函数可以直接实现这一功能,但是在WINCE6.0上确是不可以的,而PNG图片则是需要挂上DLL或者C#托管代码,可惜我的硬件不是自己公司做的,是别的垃圾公司做的一个WINCE空壳,也就包括了硬件与基本驱动,其他什么都没有,连源码也是没有的,那意味着连基本内核修改我都是做不到的。由于本人完全没有学过WINCEMFC碰到的情况也很少,所以从接手这个屏到现在过了三个多星期,实现的功能有限,包括是控件编写、串口通讯、打开文件处理,然后这些都还好,难的还是WINDOW上面那讨厌的刷新抖动,为了尽量让界面显示正常,用了很多办法,其中就包括了显示图片背景这块。

从目前的情况看我只能显示BMP,但是如果不显示出透明效果的话,界面会非常难看,毕竟当背景也是图片的时候,那些边边角角太难看了,特别是当有多页面的时候,图片不想经常用ps改来改去,于是上网找了下TransparenBlt的实现原理从而实现这个功能。

首先看下现有资源

  要显示的图片

背景图片

  //首先需要的参数有下面几个
  //显示dc
  CClientDC  pDc(this);  
   //刷新区域大小
   CRect rc;        
  //分别是要显示 的图片DC,位掩DC,以及显示缓冲DC. 
	CDC imageDc,maskDc,dcMem; 
  //背景填充图片DC
  CDC bgDc;     
  //要显示 的图片,内存缓冲,位掩缓冲             
  CBitmap bmp,memBitmap,maskBmp,bgBmp;
  //透明背景的颜色,这个颜色后面显示的时候会给忽略
  COLORREF TransParentColor;

  //获取刷新区域
 	GetClientRect(rc);
  ClientToScreen(rc);
  //读取要显示的两个图片
  bmp.LoadBitmap(IDB_BITMAP1);
  bgBmp.LoadBitmap(IDB_BITMAP_BG);
  //创建一个单色图片来实现空心区域选择的位掩
  maskBmp.CreateBitmap(rc.Width(),rc.Height(), 1,1,NULL);
  //创建一个跟当前设备相关的显示缓冲,为了保证显示正常,它的指针必须是显示的dc.
  memBitmap.CreateCompatibleBitmap(&pDc, rc.Width(),rc.Height());
  
  //创建必要dc
  imageDc.CreateCompatibleDC(NULL);
  maskDc.CreateCompatibleDC(NULL);
  dcMem.CreateCompatibleDC(NULL);
  bgDc.CreateCompatibleDC(NULL);
  
  //为dc选择缓冲
  dcMem.SelectObject(&memBitmap);
  imageDc.SelectObject(&bmp);
  maskDc.SelectObject(&maskBmp);
  bgDc.SelectObject(&bgBmp);

开始真正的功能部分

  //首先根据图片来获取有效显示区域
  //透明色
  maskDc.SetBkColor(RGB(0,0,0));
  imageDc.SetBkColor(TransParentColor);
  //采用SRCINVERT模式填充能够实现将有效区域与无效区域区分开来,	//因为maskDc是单色的,只有白色与黑色两种,而图片dc背景设成透明色后
  //会将透明色当成无效色,而其他颜色都是有效色
  	maskDc.BitBlt(0,0,rc.Width(),rc.Height(),&imageDc,0,0,SRCINVERT);
  // 这时候maskDc里面的图形是这样的,其中有效区域成了黑色,无效区域成了白色
   //这是因为本身maskDC里面是单色的,它的所有点数据只会是黑色(RGV(0,0,0)或者白色(RGV(255,255,255),而在imageDc里面设置了透明色之后,根据SRCINVERT的用法,透明色区域都会变成白色(有效),有效色的地方反而成了黑色

扫描二维码关注公众号,回复: 3773273 查看本文章
  //在显示缓冲中利用位掩空洞来实现填充
  //这里有一个问题,有个会问为什么要多创建一个dc缓冲而不直接刷到imageDc里面去呢?
  //其实在网上其实相关例程也会这么处理,也就是直接刷到图片缓冲上去来实现这个效果,
  //但是实际上我在WINCE这么做是不行的,它无法把透明色刷掉,
  //不知道是不是因为BitBlth函数与WINDOWS上有区别还是CDC有区别,
  //所以这里只能用创建一个显示缓冲来实现
  dcMem.BitBlt(0,0,rc.Width(),rc.Height(),&imageDc,0,0,SRCCOPY);
	dcMem.SetBkColor(RGB(0,0,255));
  dcMem.BitBlt(0,0,rc.Width(),rc.Height(),&maskDc,0,0,SRCINVERT);
  
  //这样就能得到下图,要透明的部分已经给虑掉了
  //这里有个技巧,如果你的图片背景本来就是黑的,那么上面的dc缓冲那步是可以不要的
  //(我猜的,因为这时候并不需要将透明部分变黑)。 

//用背景图片填充pDc.BitBlt(0,0,rc.Width(),rc.Height(), m_dcBk,rc1.left,rc1.top,SRCCOPY);//利用位掩吧要显示的bmp之外的背景都填充成背景图片,注意颜色,如果设定成背景黑、字色白,那么填充区域就反了,因为我们的位掩有效区域应该是黑色部分,这部分不应该填充的。  pDc.SetBkColor(RGB(255,255,255));pDc.SetTextColor(RGB(0,0,0));pDc.BitBlt(0,0,rc.Width(),rc.Height(), &maskDc,0,0,SRCAND);//这时候边框已经填充完毕了

/最后将要显示的图片缓冲填充过去,完成
  pDc.BitBlt(0,0,rc.Width(),rc.Height(), &dcMem,0,0,SRCPAINT);


参考资料:

http://hi.baidu.com/liuhuaxi2009/item/b22dec10de7b0e9b99ce33c0

这应该是我找的最靠谱的了,原理说的很明白,要不我还真弄不出来,不过里面的代码不适合WINCE,原因就是出现了上面的问题。其他那些只会瞎扯跟抄的,我只能默默对那群人竖起中指---真心是在害人啊。。。

注意,这代码是完成抽出来的做示例的,没有编译调试,但是如果用自己的代码给你们,反而会让你们看不懂,因此才整理了下,加了很多注释,在我的WINCE MFC是能正常显示的,但是有一个问题,就是抖动,现在在着手把抖动去掉。


 

猜你喜欢

转载自blog.csdn.net/xuzhenglim/article/details/12007321
今日推荐