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

简介: 转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/43532791                  半透明异形窗体的功能在之前维护的老版本的duilib里面已经有了基本的功能,但是因为一直存在较多的缺陷,所以我一直建议少用,就连我自己写仿酷狗项目也只是在几个小地方用了半透明异形窗体。

转载请说明原出处,谢谢~~:http://blog.csdn.net/zhuhongshu/article/details/43532791

       

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


         总体来说,为了给官方原本的duilib391版本库增加窗体半透明异形功能,需要修改的类如下:


         1、CManagerUI类的WM_PAINT消息处理代码

         2、CRenderEngine类的文字渲染函数、和背景填充函数、贴图函数

         3、CEditUI类的win32 edit创建函数

         4、CRichEditUI类的光标绘制函数(自绘光标,需要结合CManagerUI类的相关代码)

         5、给CManagerUI类增加自绘CRichEditUI光标的一系列函数

         6、处理窗体类的最小化还原小(需要结合CManagerUI类的相关代码)

         7、给CManagerUI类增加最小化还原后的消息处理代码,为了在半透明状态下完全刷新窗体


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


         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获取的区域。另外我添加了m_rcInvalidate变量,来自己管理需要更新到区域,拟补GetUpdateRect函数获取信息不足的问题。


还没有完全解决的地方


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

      

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


        2、RichEdit控件虽然可以正常使用,但是由于他内部渲染文字时没有处理透明通道,所以会导致文字穿透。出现文字穿透的现象只有在RichEdit控件完全无背景色或者背景图片的情况下。


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


    目前需要注意的就是RichEdit控件的使用,如果让RichEdit直接暴露在全透明的地方,文字渲染就会有问题。如果RichEdit设置了背景色或者背景色,或者他的父控件设置了背景色背景图,则全完没有问题。不过好在,应该没有什么地方需要让RichEdit直接暴露在全透明的位置。前面发的效果图的文本框就是用RichEdit做的。


       如果使用RichEdit的时候发现了穿透现象,建议更换textcolor的值或者bkcolor的值来修复问题。



总结:


        由于这次修改的地方比较多,设计的文件和代码也比较乱,我就没办法单独的提供某个源文件了。具体的修改可以通过svn来对比新版本和旧版本的代码来得知。源码和demo我都更新到了我的库中,支持duilib和uilib:点击打开链接



Redrain  2015.2.5 


目录
相关文章
|
C#
抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单
原文:抛砖引玉 【镜像控件】 WPF实现毛玻璃控件不要太简单 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Vblegend_2013/article/details/83447420 ...
1803 0
|
人工智能 搜索推荐 C#
Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
结合Photoshop和WPF,共同创建一个矢量的个性化进度条。
551 0
Photoshop和WPF双剑配合,打造炫酷个性的进度条控件
|
C#
WPF一步步实现完全无边框自定义Window(附源码)
原文:WPF一步步实现完全无边框自定义Window(附源码)    在我们设计一个软件的时候,有很多时候我们需要按照美工的设计来重新设计整个版面,这当然包括主窗体,因为WPF为我们提供了强大的模板的特性,这就为我们自定义各种空间提供了可能性,这篇博客主要用来介绍如何自定义自己的Window,在介绍整个写作思路之前,我们来看看最终的效果。
1304 0
|
C#
[原译]一步步教你制作WPF圆形玻璃按钮
原文:[原译]一步步教你制作WPF圆形玻璃按钮 图1   1.介绍 从我开始使用vista的时候,我就非常喜欢它的圆形玻璃按钮。WPF最好的一个方面就是允许自定义任何控件的样式。用了一段时间的Microsoft Expression Blend后。
1062 0
|
C#
张高兴的 UWP 开发笔记:用 Thumb 控件仿制一个可拖动 Button
  在 WPF 上可用的控件拖动方法在 UWP 上大多没用,那干脆用 Thumb 仿制一个吧。   关于 Thumb 控件的教程也不多,毕竟在 WPF 控件拖动有很多种方法, Thumb 就显得很鸡肋了。
1046 0
Qt之自定义界面(窗体缩放-跨平台终极版)
简述 通过上一节内容,我们实现了窗体的缩放,功能很不错,但是很遗憾-不支持跨平台!如果对于多平台来说,这是一个硬伤,所以,我们急需要一个能够支持跨平台的实现方案。 在网上看到过很多不同的实现方式,多多少少会存在一些问题-要么融合度太高、要么不能很好地进行移动、缩放。基于前人的分享与总结,最后,我花了很长时间来完善。独乐乐不如众乐乐,既然纯开源-那就全部分享出来。
1660 0
|
算法 容器 数据格式
duilib制作窗体动画效果
转载请说明原出处,谢谢~·http://blog.csdn.net/zhuhongshu/article/details/49026605         最近一段时间没写博客了,感觉最近没有遇到什么必须解决的bug。
2165 0