java调用dll或ocx控件(在SWT、web、java项目中调用)

插件开发 同时被 2 个专栏收录
3 篇文章 0 订阅
22 篇文章 0 订阅

java调用dll或ocx控件(在SWT、web、java项目中调用)


java调用本地dll或ocx分成三个方向:

一、在SWT中调用ocx

将ActiveX控件集成到SWT项目中,一个调用pdf查看器实例,可参看:https://www.ibm.com/developerworks/cn/linux/opensource/os-activex/
这里用的是SWT/JFace开发application中SWT自带的org.eclipse.swt.ole.win32 包可以支持内嵌OLE和ActiveX。

具体用法如下:

 //创建一个OleFrame做为OLE(或ActiveX)的框架
 OleFrame oleFrame = new OleFrame(this, SWT.NONE);
 //创建ActiveX的容器,其中的progID是ActiveX的progid,在注册表中可以找到
 OleControlSite oleControl = new OleControlSite(oleFrame, SWT.NONE, “progID”);
 //OleAutomation类用来执行ActiveX中的方法
 OleAutomation oleAutomation = new OleAutomation(oleControl);
 //将ActiveX显示在application中
 oleControl.doVerb(OLE.OLEIVERB_SHOW);

调用AcitveX中方法的具体过程:

1、不带参数的方法调用

 //获取Method Name的ID,Method Name为ActiveX中具体的方法名
 int[] regspid = oleAutomation.getIDsOfNames(new String[] { "MethodName" });
 int dispIdMember = regspid[0];
 //方法调用
 oleAutomation.invoke(dispIdMember);

2、带参数的方法调用

//获取Method Name的ID,Method Name为ActiveX中具体的方法名
int[] regspid = oleAutomation.getIDsOfNames(new String[] { "MethodName" });
int dispIdMember = regspid[0];
//设置方法的具体参数。Variant数组的长度为MethodName方法参数的个数
//假设有四个参数
Variant[] rgvarg = new Variant[4];
rgvarg[0] = new Variant(fileID);
rgvarg[1] = new Variant(itdsURL);
rgvarg[2] = new Variant(idType);
rgvarg[3] = new Variant(reportURL);
//方法调用
oleAutomation.invoke(dispIdMember, rgvarg);
在swt中调用wps的例子:http://download.csdn.net/download/mr_zhaoz/10218083

二、在web中调用ocx

在HTML页面中使用ActiveX控件包含三个基本操作:

将控件放入HTML中;
将该控件下载给用户;
在用户机器上安装该控件。

 如果只是针对IE用户,在HTML中插入ActiveX控件就比较简单;如果同时兼顾IE和Netscape用户,则要做更多工作。大家知道,HTML文件由文本和各种标志 (tags)组成,ActiveX 控件对于IE在HTML中的标志是<OBJECT>,该标记有几个重要的参数特性,它们是: 


1.ID:为控件提供一个标识名称,为HTML代码提供一种访问该控件的方式。
就是说在网页内部给控件提供一个名字 ,在网页中通过这个名字访问控件。

2.CLASSID:是该控件唯一的UUID,告诉IE装入哪个对象。如果使用已经开发好的控件,它的CLASSID可以通过调用Win95或NT下的应用Regedit来查找。从开始菜单中运行该程序,展开HKEY_CLASSES_ROOT项,可以看到按字母顺序排列的注册表,找到需要使用的控件名,例如WClnt,展开时可看到一个CLSID文件夹,里面就是该控件的CLASSID。 
如果是自己用VC开发控件,该UUID可以在ActiveX控件项目中的ODL(对象描述库)文件中找到;通过查看控件的类信息注释来定位特定控件的UUID,例如,要找到CMyControl控件的UUID,则需要找到以下代码: 
		Class information for CMyControl 
		[uuid (051C4748-1262-11D2-87C1-00A024D948FB), 
		licensed, 
		helpstring("CmyControl Control"), control ] 
uuid后面括号中的内容就是该控件的UUID。 
这个CLASSID相当于身份证,通过这个数字找到在电脑上已经注册的控件。

3.CODEBASE(代码库):如果在用户机器上没有控件的当前版本,该参数告诉用户浏览器在哪里可找到要下载的控件和最新版本号.当控件作了修改后,可以更改版本号强制用户重新下载。 

4.PARAM:该标记用于设置控件的初始属性值,它有两个特性:Name和Value,即属性名称和属性值。 

此外还有一些标记,如:Width表示该控件所占的宽度,Height表示高度等,总体来说,这样一个插入控件的HTML代码和插入Java Applet的HTML代码非常相似。 

下面是一个嵌有ActiveX控件的HTML代码示例: 
<OBJECT ID="CMyControl" CLASSID="clsid:051C4748-1262-11D2-87C1-00A024D948FB" CODEBASE="http://www.mysite.com.cn/ocxdir/mycontrol.ocx#version=1,0,0,1" WIDTH=400 HEIGHT=200 ALIGN=center HSPACE=0 VSPACE=0 > </OBJECT> 
CODEBASE的设置中,若CAB文件与该WEB文件保存在同一目录下,只需写其文件名即可,即CODEBASE="mycontrol.ocx#version=1,0,0,1";#号代表此控件的版本,如果版本不同,客户端的浏览器自然会下载更新。

如果希望控件还能在Netscape中运行,除了Netscape需加装插件外,HTML也要加一些附加标记,下面的例子中EMBED段就是为 Netscape加上的。如果使用MFC开发OCX控件,则少数用户第一次访问时除了下载OCX文件外,还要下载相应的MFC DLL,下载量变大,这时可将相关文件在服务器端打包成可以在客户端自解压安装的CAB文件。经过修改后的HTML代码段如下: 
		<ALIGN="CENTER" CLASSID="clsid: 
		7BCA18C6-2178-11D2-87C1-00A024D948FB" 
		WIDTH="1200" HEIGHT="900" ID="marquee" 
		CODEBASE="http://218.168.188.188/scadaweb/ 
		WClnt.cab#version=1,0,0,1"> 
		<EMBED ALIGN="CENTER"CLASSID="clsid:7BCA18C6- 2178-11D2-87C1-00A024D948FB" 
		WIDTH="1200" HEIGHT="900" ID="marqueequot;" 
		CODEBASE="http://218.168.188.188/scadaweb/ 
		WClnt.OCX#version=1,0,0,1" 
		TYPE="application/oleobject" >

在JSP(Java Server Pages)中调用OCX可以按如下操作:

 一、 先用regsvr32 D:\TestOcx.ocx 命令注册,这是我OCX存放的路径,当然也可以直接进入到ocx存放目录下去注册(个人习惯而已)如果注册成功,会提示注册成功。需要卸载用regsvr32 D:\TestOcx.ocx /u 命令
二、 到注册表查找OCX的CLSID,regedit 打开注册表,在编辑菜单里点查找输入OCX的名字,就可以找到它的CLSID和版本号
 三 写下如下JSP代码
		<html>
		<head>
		<script type="text/javascript" language="javascript"> 
		 function show(){
				TestOcx_new.TestOcx("1");
			}
			</script>
		</head>
		   <object id="TestOcx_new" width="32" height="32"
				classid="clsid:8009643F-44E9-4698-A242-3548E86FB4DF"
				CODEBASE="<%=request.getContextPath()%>\TestOcx.ocx#version=1.0">
			</object>
		<body οnlοad="show()">
		</body>
		</html>
其中:ID可以随便起名,CLASSID就是注册表里找到的CLSID,CODEBASE就是OCX的路径,版本号也是注册表里找到的。 
(曾调试写与不写没有什么区别,不知道问题所在,在我的程序里没有写)
然后就是写方法去调用OCX里的事件了,这句TestOcx_new.TestOcx("1");
TestOcx_new就是你起的ID名,TestOcx("1")就是OCX里的方法名和你传进去的参数了。

三、在java项目中调用dll或ocx

通过Java调用OCX控件有几种方法,JNI、JACOB、Jawin等

   1.JNI 最直接的方式,也是最麻烦的方式,需要自己完成所有的工作,不推荐。

   2.Jawin 尝试了一下,效果不错,但相对来说,其编程风格更贴近Windows,离Java有点远 。

   3.Jacob 使用Jacob非常方便,Java编程风格,需要了解的知识比较少。

 Jacob的使用方法:
首先--

 1.在工程中导入 jacob.jar 这个包。
 2.把 jacob.dll 拷贝到 jdk\bin或者C:\WINDOWS\system32目录下。
   以上的两个文件您可以到网上http://danadler.com/jacob/ 下载的1.7的版本
   jacob.jar 与 jacob.dll 版本一致。
 3.注册ocx控件
  l  先把***.ocx控件放入c:\windows\system32 文件夹下
  l  在cmd命令行下,输入regsvr32  ***.ocx命令进行注册

Java代码:


1.初始化 
ActiveXComponent com = new ActiveXComponent("组件的ProgID") ;
Dispatch disp = com.getObject();
2.调用控件里面的方面
 2.1调用无参的方法,并返回一个short值

Dispatch.call(disp, "Init").getShort();
 2.2调用有一个参数的方法,并返回一个boolean值

Dispatch.call(disp,"Method",new Variant(args)).getBoolean();
 调用多个参数依次类推,注意在传递参数前,将Java中的参数转换成Variant。

bug解决:

1.java.lang.UnsatisfiedLinkError: no jacob in java.library.path
原因是:没有把 jacob.dll 拷贝到 jdk\bin或者C:\WINDOWS\system32目录下

2.Exception in thread "main" com.jacob.com.ComFailException: Can't get object clsid from progid
原因是:regsvr32  ***.ocx命令进行注册后 ,获取的progid有误;

3.Exception in thread "main" com.jacob.com.ComFailException: A COM exception has been encountered:
At Invoke of: LoadFile
Description: 灾难性故障
    at com.jacob.com.Dispatch.invokev(Native Method)
    at com.jacob.com.Dispatch.invokev(Dispatch.java:858)
    at com.jacob.com.Dispatch.callN(Dispatch.java:455)
    at com.jacob.com.Dispatch.call(Dispatch.java:544)
    at com.lv.office.AIPToTest.jacob(AIPToTest.java:24)
    at com.lv.office.AIPToTest.main(AIPToTest.java:14)
 
原因是:

在OCX控件中,重写COleControl.IsInvokeAllowed (DISPID)方法,即在控件的CMyNameCtrl中增加一个方法


BOOL CMyNameCtrl::IsInvokeAllowed (DISPID)
   {
      return TRUE;
   }
用这个方法的理由是:

这个错误是由ActiveX结构设计造成的。
 在Ole4.0版本之前,外部程序是可以直接调用OCX中方法的。Ole4.0之后,每次调用控件中的方法,系统会自动检查是否允许调用,即运行COleControl.IsInvokeAllowed (DISPID)
 该方法检查控件是否正确的初始化或者是否通过持久存储接口正确加载,如果两个条件有一个满足,即返回TRUE,否则返回FALSE。
 当控件在MFC中使用时,很多细节,如初始化,都被过滤了,这样,大多数用户都不会遇到这个问题。但是,当我们从C、C++的dll中调用控件时,不满足上述条件,该方法返回FALSE,这时候再调用任何控件方法,都会出现上述异常。
  • 0
    点赞
  • 1
    评论
  • 5
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值