Vista Glossy 效果的实现
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特效了。
特效截图:
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 }
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 }
特效截图: