Entries

笔记:WPF之美和LayeredWindow的奇怪行为

……如果WPF她(“她”很美)不那么自作聪明地缓存窗体对象并且允许在第一次加载前实例化窗口(Window@user32)对象的话……那就更好了……
当然也许上面提到的两个问题是有办法解决的但问题是我实在没找到啊没找到……还有它为什么每次都要在呈现以后才重新计算最重呈现效果啊?不能在隐藏的时候先计算然后再呈现么……
让人头疼……



不过总的来说,WPF的确是个好东西,最起码她为界面美化提供了一个整体解决方案,写桌面程序的人就不用为程序的界面呈现引擎(这个词是我顺口胡诌出来的)伤脑筋了……

比方说她提供了皮肤定制的功能(好像在哪看到过……不过较真起来的话我也不太确定啦)、在Layered Window的基础上让程序猿可以轻松地为整窗体的各部分使用不同的透明度哇哈哈哈……



说到Layered Window,有经验的人应该知道想做半透明窗体总是要跟这个玩艺打交道的……而且还总是要弄得焦头烂额……
如果想用它做半透明每部分透明度还不一致的界面的话那可是相当相当的麻烦,自绘半透明窗之后窗体和上面的所有控件就都不再理会WM_PAINT了,所以上面什么控件也显示不出来(但它们的确还在该在的位置)、作什么操作也完全看不到反应……
我在学习这种技术的时候我就闷闷地想:它为什么会这样呢为什么会这样呢为什么会这样呢……肯定也有不少人这么想过吧……?

后来有一天玩狐狸的时候我想通了,问题的关键就是Layered Window这东西根本就不是设计给你做交互界面用的!
……
这东西最初设计出来是给菜单(其实我一直觉得这个应该叫“选单”)和气球提示窗加阴影效果(鼠标光标那个阴影是在另一个层面上的东西)和进行拖拽的时候提供虚影提示用的!
关于拖拽的虚影,请在狐狸上选择大段内容,或者在Windows 2000以上的系统中选择多个文件,然后进行拖动……你会发现虚影的透明度从鼠标位置呈辐射状向外递增……

上边说的这两种用途(阴影和拖拽虚影)都是不需要也绝对不应该对WM_PAINT作任何反应的,所以为这个目的设计的UpdateLayeredWindow函数当然要阻止WM_PAINT到达窗口上了!
至于后来出现的设计界面的用法,应该完全在微软的预料之外……



Layered Window翻译过来就是“层化的窗口”,意思就是说,这个窗口和其它窗口不在同一层……
这个“不在同一层”如果再深入一点说的话,就是所有不是Layered Window的窗口,它们使用的呈现DC其实在系统内部都是映射到同一个物体上的,这个物体可能叫“桌面”——管它叫什么呢——所以如果程序提取两个窗口重叠到一起的部分,只会提取到最上面的那个……

首先是微软的工程师不知道出于什么目的设计了半透明窗口这一功能,由于半透明窗口下方的窗口内容可能随时发生改变,如果让窗口时刻留意其下方的其它窗口的变化……这好像太蠢了点,所以就出现了Layered Window——这样的话不管哪个覆盖了哪个,其它窗口怎么变和层化窗口都互不影响,最终操作系统会把它们合并到一起画到显示器上……
而Layered Window之所以叫Layered Window,就是因为要实现和其它窗口互不影响这个目的,这个窗口就不能和其它窗口共享“画布”……也就是说,对于每个Layered Window,Windows都单独划分了一块内存给它用……
也就是说……Layered Window本身是比较吃内存的东西……借助工具在各种完全没必要透明的窗口上使用半透明效果(包括边框和阴影)也是个相当蠢的主意……

有经验的人应该知道,对于Layered Window,在程序中用一般的抓取图像的方法是抓不到的……需要多设置一个Flag才可以……
如果不设置Flag,抓取整个桌面的时候就会抓不到Layered Window,而单独抓取一个Layered Window的时候,效果会像抓取了一个不透明窗口一样……
这种问题也出现在QQ的抓图功能上(现在怎样我就不知道了,Vista上面有点特别)。

在Windows Vista上面,又是一种情况。如果不启用DWM,一切和Vista以前的Windows一样;如果启用了DWM,就会发现就算不设置屏幕合成Flag也能抓到半透明窗,而且连全加速(当然Vista中有没有非全加速也是个值得探讨的问题)的DirectX呈现也能捕捉到!
原因是DWM本身使用了硬件加速,启用了DWM以后所有的屏幕输出都是DirectX输出结果,自然也就不分什么层化(严格说起来,还是有层化概念的)和全速表面了……而且看起来DWM还接管了关于图像捕捉的API,这样抓图程序不经修改就可以抓取DWM的输出图像了……



DWM和毛玻璃效果是微软的一个尝试(当然,有不少的人认为这种尝试没什么意思,只会消耗系统资源),而另一个尝试就是同样跟Windows Vista一起到来的WPF
我虽然不能确定微软设计WPF最重要的原因是什么,但很明显的——微软注意到了程序猿们用半透明窗口设计程序界面的尝试,并且微软知道这种尝试有多大困难,所以“顺便”地用和以往完全不同的方式(理论上说,传统Windows程序的界面上大部分控件都是一个个的“窗口”,通过特殊手段甚至可以让这些控件产生和“普通窗口”一样的效果……这也是为什么有些人喜欢用“窗体”而不是用“窗口”……而每个控件都是一个独立窗口也就意味着每个控件都要消耗很多的资源……)提供界面技术,让程序猿可以轻松地使用半透明窗体(和皮肤化)功能。



WPF究竟有多少令人惊讶的能力,这个我就说不清了,毕竟我也不过是刚刚开始了解她……
也许在日后的深入了解中会有很多惊喜吧=_,=

(FC2的Tag不支持中间加空格,所以写成了LayeredWindow
引用此文章(FC2博客用户)
http://shinron4.blog126.fc2blog.us/tb.php/28-645770df

引用

留言

发表留言

发表留言
只对管理员显示

Appendix

自我介绍

优雅的神棍 / Elegant Tales

Author:优雅的神棍 / Elegant Tales
神棍你好,神棍再见。

最新引用

QR

QR

羔羊们啊

加为好友

和此人成爲好友

搜寻栏