看完这篇文章,可以开发如下的界面:
没有嵌入Active X控件的视图:
嵌入浏览器控件,并显示 www.blogjava.net的主页:
在Windows系统下,OLE和Active X控件是两个非常吸引人的技术,它们的基础都是COM。OLE的体验,就是平时我们可以把Excel表格嵌入Word文档,或者把PDF嵌入浏览器显示一样,而Active X控件更是无处不在,做VB开发和网页开发的人都应该很熟悉。使用Windows系统中丰富的Active X控件资源,我们可以实现功能非常强大的程序。
在Windows平台下,SWT图形工具包提供了对OLE的支持,Active X控件和OLE文档都可以被很方便地嵌入SWT窗口部件或者JFace部件,在这里,我只讨论将Active X控件插入视图。
在一个视图中包含一个Active X控件需要两个对象的支持,即一个OleFrame和一个OleClientSite对象。如果需要创建一个OLE应用,需要先后创建他们。创建OleFrame对象比较简单,OleFrame类定义在org.eclipse.swt.ole.win32中,创建OleFrame对象只需要简单的new就可以,如下:
在OleFrame的基础上就可以创建OleClientSite对象,创建该对象需要知道控件的programID,这个ID的信息存放在windows的注册表中。在我们这篇文章的例子中,我们使用的是一个浏览器控件,那么我们怎么知道浏览器控件的ProgID呢?我使用的是Visual Studio 2003自带的OleView工具,如下图:
可以看到,Microsoft Web 浏览器的ProgID为Shell.Explorer.2,我们可以这样创建OleClientSite对象:
创建对象后,还需要激活,才能够在RCP程序中对这些OLE对象进行操作。如下:
client.doVerb(OLE.OLEIVERB_SHOW);
然后,我们需要操作这个Active X控件,调用它的方法,或者设置它的属性。比如在此例中,我们需要调用浏览器控件的navigate方法,以便我们的浏览器控件显示 www.blogjava.net的主页。对Active X控件的操作通过OleAutomation对象来实现,创建OleAutomation对象的方法如下:
OleAutomation automation =
new OleAutomation(client);
再通过automation.invoke()来调用Active X控件的方法,其中invoke方法有几种重载形式,有只带一个int参数的,也有带int和Variant[]两个参数的,其中的int参数表示要调用的Active X控件的方法的ID,Variant[]参数就是要传递给Active X控件的方法的参数。
这里我们要说一说Variant类,这个类提供了多个构造函数,可以方便的将int,float,long,double,string等等基本数据类型封装为Variant,比如我们要传递给浏览器控件的navigate方法的地址参数:
Variant url =
new Variant("http://www.blogjava.net");
那么我们怎么才能得到Active X控件的方法的ID,还有它需要哪些参数呢?还是要借助前面提到的OleView.exe工具,如下图:
可以看到,Navigate方法的id为0x00000068,转化为十进制就是104,而它需要的参数第一个是一个字符串,其它的都是可选的,因此,我们可以这样调用它的方法:
Variant url =
new Variant("http://www.blogjava.net/");
automation.invoke(104,
new Variant[]
{url});
下面,贴出本文例子中的视图的代码和菜单Action的代码,在写这篇文章之前,我一直在探索怎样从菜单控制视图,后来发现是这样:
window.getActivePage.getViewReferences();
虽然我不知道Eclipse中Page的概念究竟是什么,但是只要能找到我要操作的视图就可以了。视图的代码如下:
OleView.java
在这个视图中,我创建了OleFrame对象,并让它是public的,至于OleClientSite和OleAutomation对象,我们在点击菜单项后创建。菜单动作的代码如下:
OpenFileAction.java
根据前面几节将的内容配置plugin.xml和修改Perspective.java的代码,就可以看到文章开头的效果了。
没有嵌入Active X控件的视图:
![rcp29.JPG](https://i-blog.csdnimg.cn/blog_migrate/b8c26b7e17900a420f2c5b43925dd490.jpeg)
嵌入浏览器控件,并显示 www.blogjava.net的主页:
![rcp30.JPG](https://i-blog.csdnimg.cn/blog_migrate/39960f4be165aa2e7c8d09650f64bfc3.jpeg)
在Windows系统下,OLE和Active X控件是两个非常吸引人的技术,它们的基础都是COM。OLE的体验,就是平时我们可以把Excel表格嵌入Word文档,或者把PDF嵌入浏览器显示一样,而Active X控件更是无处不在,做VB开发和网页开发的人都应该很熟悉。使用Windows系统中丰富的Active X控件资源,我们可以实现功能非常强大的程序。
在Windows平台下,SWT图形工具包提供了对OLE的支持,Active X控件和OLE文档都可以被很方便地嵌入SWT窗口部件或者JFace部件,在这里,我只讨论将Active X控件插入视图。
在一个视图中包含一个Active X控件需要两个对象的支持,即一个OleFrame和一个OleClientSite对象。如果需要创建一个OLE应用,需要先后创建他们。创建OleFrame对象比较简单,OleFrame类定义在org.eclipse.swt.ole.win32中,创建OleFrame对象只需要简单的new就可以,如下:
1
OleFrame frame =
new OleFrame(parent, SWT.NONE);
在这个构造函数中,第一个参数指的是该OleFrame的母窗口部件,即Active X控件将要被嵌入的窗口部件。
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
在OleFrame的基础上就可以创建OleClientSite对象,创建该对象需要知道控件的programID,这个ID的信息存放在windows的注册表中。在我们这篇文章的例子中,我们使用的是一个浏览器控件,那么我们怎么知道浏览器控件的ProgID呢?我使用的是Visual Studio 2003自带的OleView工具,如下图:
![rcp26.JPG](https://i-blog.csdnimg.cn/blog_migrate/2ff310d8561d0cbda70f78108c95fcdf.jpeg)
可以看到,Microsoft Web 浏览器的ProgID为Shell.Explorer.2,我们可以这样创建OleClientSite对象:
1
OleClientSite client =
new OleClientSite(frame,SWT.NONE,"Shell.Explorer.2");
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
创建对象后,还需要激活,才能够在RCP程序中对这些OLE对象进行操作。如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
然后,我们需要操作这个Active X控件,调用它的方法,或者设置它的属性。比如在此例中,我们需要调用浏览器控件的navigate方法,以便我们的浏览器控件显示 www.blogjava.net的主页。对Active X控件的操作通过OleAutomation对象来实现,创建OleAutomation对象的方法如下:
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
这里我们要说一说Variant类,这个类提供了多个构造函数,可以方便的将int,float,long,double,string等等基本数据类型封装为Variant,比如我们要传递给浏览器控件的navigate方法的地址参数:
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
那么我们怎么才能得到Active X控件的方法的ID,还有它需要哪些参数呢?还是要借助前面提到的OleView.exe工具,如下图:
![rcp27.JPG](https://i-blog.csdnimg.cn/blog_migrate/3b93944b898cf2182ee5f12f80b3c1bd.jpeg)
![rcp28.JPG](https://i-blog.csdnimg.cn/blog_migrate/20fc0288f154affef2d43019883759b9.jpeg)
可以看到,Navigate方法的id为0x00000068,转化为十进制就是104,而它需要的参数第一个是一个字符串,其它的都是可选的,因此,我们可以这样调用它的方法:
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
下面,贴出本文例子中的视图的代码和菜单Action的代码,在写这篇文章之前,我一直在探索怎样从菜单控制视图,后来发现是这样:
window.getActivePage.getViewReferences();
虽然我不知道Eclipse中Page的概念究竟是什么,但是只要能找到我要操作的视图就可以了。视图的代码如下:
OleView.java
1
package cn.blogjava.youxia.views;
2
3
import org.eclipse.jface.action.IMenuManager;
4
import org.eclipse.jface.action.IToolBarManager;
5
import org.eclipse.swt.SWT;
6
import org.eclipse.swt.widgets.Composite;
7
import org.eclipse.ui.part.ViewPart;
8
import org.eclipse.swt.ole.win32.OleFrame;
9
10
public
class OleView
extends ViewPart
{
11
public OleFrame frame;
12![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
13
public static final String ID = "cn.blogjava.youxia.views.OleView"; //$NON-NLS-1$
14![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
15
/**
16
* Create contents of the view part
17
* @param parent
18
*/
19
@Override
20
public void createPartControl(Composite parent) {
21
frame = new OleFrame(parent, SWT.NONE);
22
23
//
24
createActions();
25
initializeToolBar();
26
initializeMenu();
27
}
28![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
29
/**
30
* Create the actions
31
*/
32
private void createActions() {
33
// Create the actions
34
}
35![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
36
/**
37
* Initialize the toolbar
38
*/
39
private void initializeToolBar() {
40
IToolBarManager toolbarManager = getViewSite().getActionBars()
41
.getToolBarManager();
42
}
43![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
44
/**
45
* Initialize the menu
46
*/
47
private void initializeMenu() {
48
IMenuManager menuManager = getViewSite().getActionBars()
49
.getMenuManager();
50
}
51![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
52
@Override
53
public void setFocus() {
54
// Set the focus
55
}
56![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
57
}
58
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
2
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
3
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
4
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
5
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
6
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
7
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
8
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
9
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
10
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
11
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
12
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
13
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
14
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
15
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
16
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
17
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
18
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
19
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
20
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
21
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
22
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
23
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
24
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
25
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
26
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
27
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
28
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
29
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
30
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
31
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
32
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
33
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
34
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
35
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
36
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
37
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
38
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
39
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
40
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
41
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
42
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
43
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
44
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
45
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
46
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
47
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
48
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
49
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
50
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
51
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
52
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
53
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
54
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
55
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
56
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
57
![](https://i-blog.csdnimg.cn/blog_migrate/8f1ba5b45633e9678d1db480c16cae3f.gif)
58
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
在这个视图中,我创建了OleFrame对象,并让它是public的,至于OleClientSite和OleAutomation对象,我们在点击菜单项后创建。菜单动作的代码如下:
OpenFileAction.java
1
package cn.blogjava.youxia.actions;
2
3
4
import org.eclipse.jface.action.IAction;
5
import org.eclipse.jface.viewers.ISelection;
6
import org.eclipse.swt.SWT;
7
import org.eclipse.swt.ole.win32.OLE;
8
import org.eclipse.swt.ole.win32.OleClientSite;
9
import org.eclipse.ui.IWorkbenchWindow;
10
import org.eclipse.ui.IWorkbenchWindowActionDelegate;
11
import org.eclipse.ui.*;
12
import cn.blogjava.youxia.views.*;
13
import org.eclipse.swt.ole.win32.OleAutomation;
14
import org.eclipse.swt.ole.win32.Variant;
15
16
public
class OpenFileAction
implements IWorkbenchWindowActionDelegate
{
17![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
18
IWorkbenchWindow window;
19
20
public void dispose() {
21
// TODO 自动生成方法存根
22![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
23
}
24![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
25
public void init(IWorkbenchWindow window) {
26
// TODO 自动生成方法存根
27
this.window = window;
28![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
29
}
30![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
31
public void run(IAction action) {
32
// TODO 自动生成方法存根
33
34
IViewReference[] vfs = window.getActivePage().getViewReferences();
35
IViewPart vw;
36
for(int i=0; i<vfs.length; i++){
37
vw = vfs[i].getView(false);
38
if(vw.getTitle().equals("使用Active X控件")){
39
OleClientSite client = new OleClientSite(((OleView)vw).frame,SWT.NONE,"Shell.Explorer.2");
40
client.doVerb(OLE.OLEIVERB_SHOW);
41
OleAutomation oa = new OleAutomation(client);
42
Variant str = new Variant("http://www.blogjava.net/");
43
oa.invoke(104, new Variant[]{str});
44
45
}
46
}
47
48
}
49![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
50
public void selectionChanged(IAction action, ISelection selection) {
51
// TODO 自动生成方法存根
52![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
53
}
54![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
55
}
56
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
2
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
3
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
4
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
5
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
6
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
7
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
8
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
9
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
10
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
11
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
12
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
13
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
14
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
15
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
16
![](https://i-blog.csdnimg.cn/blog_migrate/1fa987a29c6482f53d401256f96355eb.gif)
17
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
18
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
19
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
20
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
21
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
22
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
23
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
24
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
25
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
26
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
27
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
28
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
29
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
30
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
31
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
32
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
33
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
34
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
35
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
36
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
37
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
38
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
39
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
40
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
41
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
42
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
43
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
44
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
45
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
46
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
47
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
48
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
49
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
50
![](https://i-blog.csdnimg.cn/blog_migrate/97e794c86028c5f5b5461ae5ef440a4c.gif)
51
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
52
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
53
![](https://i-blog.csdnimg.cn/blog_migrate/ecedf933ec37d714bd4c2545da43add2.gif)
54
![](https://i-blog.csdnimg.cn/blog_migrate/d18c02628675d0a2c816449d98bda930.gif)
55
![](https://i-blog.csdnimg.cn/blog_migrate/8f1ba5b45633e9678d1db480c16cae3f.gif)
56
![](https://i-blog.csdnimg.cn/blog_migrate/4f1150b881333f12a311ae9ef34da474.gif)
根据前面几节将的内容配置plugin.xml和修改Perspective.java的代码,就可以看到文章开头的效果了。