as3-AIR在win7下实现磨砂窗体
很多学习AIR的同学都知道,这个几乎是不可能的,因为AIR有限的能力,还不能达到那种效果。我曾今也单纯地以为,只要通过AS3的模糊滤镜,就能达到窗体磨砂的效果,答案是不行的,显然没那么简单,否则为啥市面上那么多AIR怎么就没有实现窗体磨砂的案例呢。如果单纯地通过AS3的模糊滤镜,可以实现舞台内部磨砂窗体,如果只是做子窗体效果,那也挺推荐用的。但现在要做的是顶级窗体的磨砂效果。
我曾今用C++成功实现过windows7下的磨砂,那是系统的窗体,通过createWindow()创建出来的,然后调用了微软在Vista版本以上系统才有的DWM库,该库可以让开发者轻松实现磨砂窗体,这里也不再赘述,详情请看牛人的文章http://blog.iyunv.com/ntwilford/article/details/5656633
其实实现窗体磨砂并不难,难的是如何把这个技术用在AIR上面,其实这个也不怎么难,最难的是如何把AIR窗体的HWND句柄传给DLL,下面听我一步步道来。
先说如何把这个技术用在AIR上面,答案就是ANE,ANE是ADOBE为AIR开发的一个本地代码扩展功能,可以使用的语言有C/C++或者JAVA,如果是做windows应用开发的,那建议用C/C++(还有MAC OS 开发objective-c),如果做android应用开发的,那就用JAVA。本文用的C++,开发环境是VS2012(其实VS版本没啥关系,因为就使用VC库而已),系统是windows7旗舰版。这里需要注意的是,磨砂窗体需要Vista及以上的系统内核才支持的,否则会提示缺少DLL,就算有了DLL,也会出不来效果。还有就是需要主题开启Aero效果,这是废话?有些开发者为了使系统达到一定的开发效率,就把Aero关掉了,现在开启吧。本人的是台式机,Aero效果无压力。
废话不多说了,看代码:
1 package
2 {
3 import flash.display.NativeWindow;
4 import flash.external.ExtensionContext;
5 /**
6 *
7 * @author RockyF
8 * 磨砂窗体类,首先必须通过bindWindow来绑定一个窗体(为了提高效率,采用了先绑定的方案)
9 */
10 public class BlurWindow
11 {
12 private var context:ExtensionContext;
13 public function BlurWindow()
14 {
15 context = ExtensionContext.createExtensionContext("BlurWindow","");
16 }
17
18 /**
19 * 绑定窗体句柄,以提高效率
20 * @param window 要应用磨砂窗体的NativeWindow对象
21 * @return
22 *
23 */
24 public function bindWindow(window:NativeWindow):Boolean{
25 var titleOld:String = window.title;
26
27 var titleNew:String = "";
28
29 var chars:String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
30 for(var i:int = 0; i < 20; i++){
31 titleNew += chars.charAt(int(Math.random() * 26));
32 }
33 window.title = titleNew;
34
35 var result:Boolean = Boolean(context.call("bindWindow", titleNew));
36
37 window.title = titleOld;
38
39 return result;
40 }
41
42 /**
43 * 你无需传入窗体的句柄,只需要提供要应用磨砂窗体的NativeWindow对象
44 *
45 * @param padding 该磨砂窗体的内边距,这个参数在设置窗体阴影的时候很重要
46 * @param radius 磨砂窗体的圆角半径
47 * @return 返回结果该系统是否支持磨砂窗体
48 *
49 */
50 public function apply(padding:int, radius:int):void{
51 context.call("apply", padding, padding, padding, padding, radius, radius)
52 }
53
54 /**
55 * 你无需传入窗体的句柄,只需要提供要应用磨砂窗体的NativeWindow对象
56 *
57 * @param padding 该磨砂窗体的内边距,这个参数在设置窗体阴影的时候很重要
58 * @param radius 磨砂窗体的圆角半径
59 * @return 返回结果该系统是否支持磨砂窗体
60 *
61 */
62 public function applyAdvance(paddingLeft:int, paddingTop:int, paddingRight:int, paddingBottom:int, radiusX:int, radiusY:int):void{
63 context.call("apply", paddingLeft, paddingTop, paddingRight, paddingBottom, radiusX, radiusY);
64 }
65 /**
66 * 判断该系统是否支持磨砂窗体
67 * @return 返回结果该系统是否支持磨砂窗体
68 *
69 */
70 public function isSupported():Boolean{
71 var ispt:Boolean = Boolean(context.call("isSupported"));
72 return ispt;
73 }
74 }
75 }
该类提供了四个方法和一个构造方法,构造方法是要的,通过构造方法创建一个上下文环境context, 以后对DLL的调用都会通过这个context(具体了解ANE,可以查看ADOBE官方文档,这里不再赘述了)。
在new了这个类之后,需要绑定一个AIR窗体,为啥要绑定?我也是通过很多地试验得出的结论,每次都要获取AIR窗体的句柄,何不就获取一次,然后保留在DLL中呢,这样的话,每次apply一次窗体,都不会做同样的事了。
看到这里,有人就要问了,这么多废话,那个AIR窗体的句柄到底怎么传递给DLL啊?
记得我在论坛回复道:拐几个弯就行了。我猜那位兄弟是理解了我的话,然后,他就动用了WIN 32 api大军,从进程到模块,都用了遍,最后还是得不到句柄。
现在就公布答案:WIN 32 API那么多,何愁得不到一个窗体的句柄。其实,在BlurWindow这个类中,就可以看到如何传递句柄了,我就是用了窗体的title属性,很容易联想到吧,在c++端就是接收了这个title,然后通过FindWindow()来获得句柄的。然而,又有人要问,那如果有同名的窗体,那怎么办?看代码中,我拐了一个弯:我先把原窗体的title存下来,然后用一个随机的20个字母的字符串来覆盖掉,可想而知,随机的20个字母组成的字符串,要碰到相同的title,那几率是多少,很小很小,所以我忽略不计了。如果你要还是担心会重名,那建议你用MD5好了。
好了,关键的技术点我已经放出来,有意向的同学就可以开始动手了。
要是懒得动啊,那下载源码好了。源码中的效果图:
转载请注明:http://www.iyunv.com/rockyf/archive/2013/03/11/AIR_Win7_BlurWindow.html
源码下载:
BlurWindow.zip flash pro版
BlurWindow.zip flash builder版
页:
[1]