使用duilib开发半透明异形窗体程序(附源码和demo)

转载请说明原出处,谢谢~~:

半透明异形窗体的功能在之前维护的老版本的duilib里面已经有了基本的功能,但是因为一直存在较多的缺陷,所以我一直建议少用,就连我自己写仿酷狗项目也只是在几个小地方用了半透明异形窗体。不过今天在群里和其他几位朋友讨论后,发现了之前的许多问题以及解决方法。所以我立马修复了当前的库,并且写了一个半透明异形窗体的demo来测试效果。这里的半透明窗体是用UpdateLayeredWindow函数实现的,并不是双层窗体。

在这篇博客里,我主要说明一下一下几点:

1、之前版本使用半透明异形窗体存在的一些问题

2、新版本里的大致解决方法

3、还没有完全解决的地方

4、使用半透明异形窗体应该注意的地方

废话不多说,先把demo的效果图展示一下:

存在的问题和解决办法:

问题1:字体穿透

这是之前的半透明窗体的最大问题,由于GDI本身的缺陷,导致渲染文字时缺少透明通道信息,导致文字穿透,之前使用heat群主的alpha修复方法,但是还不能完全解决这个问题。为此我把文字渲染函数修改。当窗体是透明模式或者用户开启了gdi+文字渲染模式,就用gdi+来渲染文字。开启半透明模式的方法是设置xml布局的Window标签的bktrans属性为true。开启gdi+文字渲染模式的方法是设置xml布局的Window标签的gdiplustext属性为true。bktrans属性和gdiplustext属性是独立的。(如果感觉默认的GDI文字渲染效果不够好时,就可以使用gdiplustext属性得到更好的渲染效果)。

GDI+的渲染效率是出名的低,不过据我测试文字渲染才用GDI+的话看不出影响效率。

问题2:字体穿透2

还是字体穿透的文字,即使把文字渲染改成gdi+再配合alpha修复,但是依然发现会出现字体穿透的问题,这也是之前让我纳闷的地方。而今天我做了许多测试后发现,原来和控件的背景色有关。如果不设置控件的背景色或者背景色是半透明的,渲染文字就不会穿透,而设置了背景色而且不透明就会穿透,背景色填充是CRenderEnghine类的DrawColor函数负责的。观察源码后发现。如果背景色的透明度设置为FF(也就是不透明)的话,就会使用GDI函数来填充背景色,而如果设置了透明度,则使用AlphaBlend函数来使用一个位图来填充背景。所以问题还是出在透明通道上(说明alpha修复还不能完全解决相关的问题)。

所以只要让duilib填充背景色时包含透明信息就不会导致穿透了,而后阅读代码发现duilib默认的alpha背景色填充代码比较多。我个人感觉不如直接用gdi+来填充背景色。代码如下:

if( color <= 0x00FFFFFF ) return;Gdiplus::Graphics graphics( hDC );Gdiplus::SolidBrush brush(Gdiplus::Color((LOBYTE((color)>>24)), GetBValue(color), GetGValue(color), GetRValue(color)));graphics.FillRectangle(&brush, rc.left, rc.top, rc.right – rc.left, rc.bottom – rc.top);

这个代码比较简单,应该不会影响效率吧?

问题3:窗体刷新不完整

原来的库编译的半透明异形程序,有时会出现窗体刷新不完整的情况,比如:把一个半透明程序的一般拖到屏幕外侧,然后双击标题栏让他最大化,接着再最小化,然后把程序再拖到屏幕内,就会发现原来在屏幕外部的界面完全没有绘制出来。

导致这个问题的原因,是因为要使用异形窗体就需要使用UpdateLayeredWindow函数,而使用了这个函数后窗体的绘制就由UpdateLayeredWindow来接管了,,许多情况下WM_PAINT消息就不会触发。跟踪代码后发现是因为程序还原后调用GetUpdateRect函数获取更新区域信息时信息不完整导致的。所以我在CManagerUI类中拦截了WM_SYSCOMMAND消息,发现程序从最大化还原后就设置m_bIsRestore为真,把m_bIsRestore作为标志。当在WM_PAINT中刷新界面时如果m_bIsRestore为真则刷新整个程序界面而不只是GetUpdateRtect获取的区域。

还没有完全解决的地方

前面说明的一些问题解决后,配合alpha修复的代码。基本就可以使用半透明异形窗体了。不过还是存在一些没有解决的问题:

1、半透明模式下Edit控件的效果不好。duilib的Edit控件内部调用了Win32的edit控件,为了在半透明模式下使用它,不得不使用WS_POPUP样式窗体Win32的edit控件。但是这样窗体后会在外观上出现一些问题。就是单击duilib的Edit控件时会闪一下。所以建议使用RichEdit控件来代替Edit,而且RichEdit控件是支持半透明或者全透明背景的。

忍耐力较诸脑力,尤胜一筹。

使用duilib开发半透明异形窗体程序(附源码和demo)

相关文章:

你感兴趣的文章:

标签云: