Feeling

    三人行,必有我师焉

   ::  :: 新随笔 :: 联系 ::  :: 管理 ::
  85 随笔 :: 0 文章 :: 392 评论 :: 0 Trackbacks
Glossy 效果,顾名思义,就是玻璃质的光泽透明的效果,在Windows平台下的应用越来越广泛,从Media Player10开始,它的button已经运用上了此效果。现在但凡是微软新发布的软件,十有八九都带有glossy特效。Glossy 效果使用了Gdi Plus的API,因此在Win98和Win2000下,必须安装gdiplus.dll才能使用,此动态链接库不大,只有700多K,但是想要在自己的应用程序中画出绚丽多彩的效果,那是少不了这个小东西的。关于Glossy效果的描述,可以参见CodeProject上的一片文章WindowsVistaRenderer,http://www.codeproject.com/KB/vista/WindowsVistaRenderer.aspx

Glossy特效有一个重要的组成部分,就是椭圆的光晕,此效果在Linux下可能并没有实现(并未下定论,我还没有深入研究过Linux下的图形库), 所以SWT的Gdip并没有将其公开出来,而是放入custom的API里,也就是说,你可以自行调用此效果的API,但是SWT并不负责为你提供封装, 因此你并不能使用GC来实现该特效,这对我们的界面开发极为不利,自己调用Gdip的API,繁琐不说,还很容易导致JVM退出。

为了能够方便的使用GC来画出此特效,我们不得不采用一些非常规的手段:反射。利用反射我们可以拿到GC的一些内部数据,在这个地方,我们只需要拿到GCData就可以,它包含了画图所需要具备的元素。Glossy效果需要使用PathGradientBrush,我们把这个刷子赋给GCData,就可以使用GC来画出glossy特效了。
 1 public class GCExtension {
 2 
 3     private GC gc;
 4 
 5     private GCData data;
 6 
 7     public GCExtension(GC gc) {
 8         this.gc = gc;
 9         data = getGCData(gc);
10     }
11 
12     public void fillGradientPath(Path path, float[] centerPoint,
13             Color centerColor, int centerColorAlpha, Color[] surroundColors,
14             int[] surroundColorAlphas) {
15         if (gc == null || gc.handle == 0)
16             SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
17         if (path == null || centerPoint == null || centerColor == null
18                 || surroundColorAlphas == null)
19             SWT.error(SWT.ERROR_NULL_ARGUMENT);
20         if (path.handle == 0 || centerPoint.length < 2
21                 || centerColor.handle == 0
22                 || surroundColors.length != surroundColorAlphas.length)
23             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
24         for (int i = 0; i < surroundColors.length; i++) {
25             if (surroundColors[i] == null || surroundColors[i].handle == 0)
26                 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
27         }
28 
29         int brush = Gdip.PathGradientBrush_new(path.handle);
30         if (brush == 0)
31             SWT.error(SWT.ERROR_NO_HANDLES);
32         PointF point = new PointF();
33         point.X = centerPoint[0];
34         point.Y = centerPoint[1];
35         Gdip.PathGradientBrush_SetCenterPoint(brush, point);
36 
37         int colorRef = centerColor.handle;
38         int rgb = ((colorRef >> 16& 0xFF| (colorRef & 0xFF00)
39                 | ((colorRef & 0xFF<< 16);
40         int color = Gdip.Color_new(centerColorAlpha << 24 | rgb);
41         if (color == 0)
42             SWT.error(SWT.ERROR_NO_HANDLES);
43         Gdip.PathGradientBrush_SetCenterColor(brush, color);
44         Gdip.Color_delete(color);
45 
46         int[] colors = new int[surroundColors.length];
47         for (int i = 0; i < surroundColors.length; i++) {
48             colorRef = surroundColors[i].handle;
49             rgb = ((colorRef >> 16& 0xFF| (colorRef & 0xFF00)
50                     | ((colorRef & 0xFF<< 16);
51             colors[i] = Gdip.Color_new(surroundColorAlphas[i] << 24 | rgb);
52             if (colors[i] == 0)
53                 SWT.error(SWT.ERROR_NO_HANDLES);
54         }
55         Gdip.PathGradientBrush_SetSurroundColors(brush, colors,
56                 new int[] { colors.length });
57         for (int i = 0; i < surroundColors.length; i++) {
58             Gdip.Color_delete(colors[i]);
59         }
60         data.gdipBrush = brush;
61         boolean advanced = gc.getAdvanced();
62         if (!advanced)
63             gc.setAdvanced(true);
64         int mode = Extension.GetPolyFillMode(gc.handle) == Extension.WINDING ? Gdip.FillModeWinding
65                 : Gdip.FillModeAlternate;
66         Gdip.GraphicsPath_SetFillMode(path.handle, mode);
67         Gdip.Graphics_FillPath(data.gdipGraphics, data.gdipBrush, path.handle);
68         if (!advanced)
69             gc.setAdvanced(false);
70         if (data.gdipBrush != 0) {
71             Gdip.PathGradientBrush_delete(data.gdipBrush);
72             data.gdipBrush = 0;
73         }
74     }
75 
76     private GCData getGCData(GC gc) {
77         GCData data = null;
78         try {
79             Object obj = null;
80             Field field = gc.getClass().getDeclaredField("data");
81             if (field != null) {
82                 field.setAccessible(true);
83                 obj = field.get(gc);
84             }
85             if (obj != null && obj instanceof GCData)
86                 data = (GCData) obj;
87         } catch (Exception e) {
88 
89         }
90         return data;
91     }
92 }

特效截图:

posted on 2008-04-30 15:54 三人行,必有我师焉 阅读(3471) 评论(3)  编辑  收藏

评论

# re: Vista Glossy 效果的实现 2008-04-30 17:46 BeanSoft
不错,已经开始深入Windows内核了,呵呵。支持下,Java做界面最后总得进入系统级,没办法。  回复  更多评论
  

# re: Vista Glossy 效果的实现 2008-04-30 17:52 三人行,必有我师焉
现在Linux GTK Extension也已经启动了,虽然无法做到API一致,但是希望尽量扩大2个系统的交集。  回复  更多评论
  

# re: Vista Glossy 效果的实现[未登录] 2008-05-10 10:55 stonebow
请问GC是什么呢?  回复  更多评论
  


只有注册用户登录后才能发表评论。


网站导航:
 
GitHub |  开源中国社区 |  maven仓库 |  文件格式转换