杰瑞科技汇

Java如何调用ActiveX控件?

核心原理:Java 与 COM 的桥梁

想象一下,Java 运行在 Java 虚拟机中,是一个“外国人”,而 ActiveX 控件是基于 Windows 的 COM (Component Object Model) 技术,是“本地人”,Java 无法直接和“本地人”沟通。

Java如何调用ActiveX控件?-图1
(图片来源网络,侵删)

我们需要一个“翻译官”或“中间人”,这个“中间人”JNI (Java Native Interface)特定的库,这些库能够:

  1. 在 Java 和 Windows 之间建立一座桥。
  2. 让 Java 能够创建、调用和操作 COM 对象(也就是你的 ActiveX 控件)。
  3. 处理数据类型之间的转换(Java 类型 ↔ COM/VB 类型)。

最主流和推荐的“桥梁”库是 Jacob (Java-COM Bridge)


推荐工具:Jacob (Java-COM Bridge)

Jacob 是一个开源的 Java 库,它使用 JNI 来提供对 Windows COM 组件的访问,它轻量级、易用,并且社区活跃,是解决 Java 调用 ActiveX 问题的首选方案。

优点:

Java如何调用ActiveX控件?-图2
(图片来源网络,侵删)
  • 简单易用:API 设计直观,学习成本低。
  • 轻量级:不需要庞大的 JRE 或复杂的配置。
  • 开源免费:可以自由使用和修改。

详细步骤:使用 Jacob 调用 ActiveX 控件

假设我们要调用一个常见的 ActiveX 控件:Microsoft Web Browser (Shdocvw.dll),用来在 Java 程序中嵌入一个 IE 内核的浏览器窗口。

第 1 步:准备工作

  1. 下载 Jacob

  2. 配置 Jacob 库

    • 解压下载的 zip 文件,你会看到 jacob.jarjacob-x.x.x-x64.dll (或 jacob-x.x.x-x86.dll)。
    • jacob.jar:这是 Java 的库文件,需要添加到你的项目的 classpath 中。
    • .dll 文件:这是 JNI 的本地库文件。
      • 如果你使用的是 64位 的 JDK 和 64位 的操作系统,请使用 jacob-1.21-x64.dll
      • 如果你使用的是 32位 的 JDK 和 32位 的操作系统,请使用 jacob-1.21-x86.dll
      • 重要:JDK 的位数必须与 DLL 的位数一致,否则会报 UnsatisfiedLinkError
  3. 放置 DLL 文件

    Java如何调用ActiveX控件?-图3
    (图片来源网络,侵删)
    • 方法一(推荐,便于开发):将 DLL 文件复制到你的 Java 项目的 src/main/resources 目录下,Maven 或 Gradle 在打包时会自动将其复制到最终的输出目录(如 target/classesbuild/classes)。
    • 方法二(运行时指定):将 DLL 文件放在一个固定的路径(C:\jacob_dll),然后在运行 Java 程序时,通过 -Djava.library.path="C:\jacob_dll" 参数来指定其位置。
    • 方法三(系统路径):将 DLL 文件所在的目录添加到系统的 PATH 环境变量中,不推荐,因为可能污染全局环境。

第 2 步:编写 Java 代码

我们将创建一个简单的 Swing 应用,其中包含一个由 ActiveX 控件驱动的浏览器窗口。

import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;
import javax.swing.*;
import java.awt.*;
/**
 * 一个使用 Jacob 在 Java Swing 中嵌入 ActiveX WebBrowser 控件的示例。
 */
public class ActiveXBrowserExample {
    public static void main(String[] args) {
        // 确保在事件调度线程中创建和显示 GUI
        SwingUtilities.invokeLater(() -> {
            // 创建主窗口
            JFrame frame = new JFrame("Java 调用 ActiveX WebBrowser 示例");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setSize(800, 600);
            // 创建一个面板来放置 ActiveX 控件
            JPanel panel = new JPanel(new BorderLayout());
            frame.setContentPane(panel);
            try {
                // 1. 创建 ActiveX 组件对象
                // CLSID 是 WebBrowser 控件的唯一标识符
                // 可以从系统注册表中找到,或在网上搜索 "WebBrowser CLSID"
                String clsidWebBrowser = "{8856F961-340A-11D0-A96B-00C04FD705A2}";
                ActiveXComponent webBrowser = new ActiveXComponent(clsidWebBrowser);
                // 2. 获取控件的 Dispatch 对象,用于调用其方法
                Dispatch browser = webBrowser.getObject();
                // 3. 将 ActiveX 控件嵌入到 Swing 容器中
                // 这是 Jacob 的一个关键功能,它需要一个 AWT 的 Container
                // panel 是一个 Swing 的 JPanel,但它继承自 AWT 的 Container
                Handle handle = new Handle(panel);
                Variant result = Dispatch.call(browser, "Navigate", "http://www.baidu.com");
                // 将控件与句柄关联
                Dispatch.put(browser, "Parent", handle.getHandle());
                // 4. 将包含 ActiveX 控件的面板添加到主窗口
                panel.add(handle, BorderLayout.CENTER);
            } catch (Exception e) {
                e.printStackTrace();
                JOptionPane.showMessageDialog(frame, "初始化 ActiveX 控件失败!\n请确保已正确安装 Jacob DLL 并位数匹配。", "错误", JOptionPane.ERROR_MESSAGE);
            }
            // 显示窗口
            frame.setVisible(true);
        });
    }
    /**
     * 一个内部类,用于封装 AWT Handle,这是 Jacob 将 ActiveX 控件嵌入到 Swing 容器所需的关键部分。
     * 它本质上是一个 Windows 窗口的句柄。
     */
    static class Handle extends java.awt.Component {
        public Handle(Container parent) {
            parent.add(this);
        }
        public long getHandle() {
            return this.getHandle();
        }
    }
}

第 3 步:配置项目并运行

如果你使用 Maven (推荐)

pom.xml 文件中添加 jacob.jar 的依赖:

<dependencies>
    <!-- Jacob 依赖 -->
    <dependency>
        <groupId>net.sf.jacob-project</groupId>
        <artifactId>jacob</artifactId>
        <version>1.21</version>
        <!-- scope provided 表示运行时需要,但打包时由 Maven 处理 -->
        <scope>provided</scope> 
    </dependency>
</dependencies>

确保你的 Maven 项目结构是标准的,并且将 jacob-x.x.x-x64.dll 放在 src/main/resources 目录下,Maven 在构建 jar 包时,可以使用 maven-resources-plugin 来将 DLL 文件复制到 target/classes 目录,这样运行时就能自动找到它。

运行程序

  1. 编译你的 Java 代码。
  2. 运行生成的 .class 文件,确保 JVM 能找到 jacob.jar.dll 文件。
    • 如果使用 IDE (如 IntelliJ IDEA 或 Eclipse),只需将 jacob.jar 添加为库,并将 DLL 放在 resources 目录下,IDE 通常会自动处理路径。
    • 如果通过命令行运行:
      # 假设 DLL 在 target/classes 目录下
      java -cp ".;target/classes;jacob.jar" com.your.package.ActiveXBrowserExample

      注意:Windows 下路径分隔符是 。

运行成功后,你应该会看到一个窗口,其中显示的是百度主页,而这个窗口是由 ActiveX WebBrowser 控件渲染的。


其他调用方法简介

除了 Jacob,还有其他一些技术,但它们各有缺点,通常不作为首选。

JACOB (Java-ActiveX Bridge)

  • 注意:这不是 Jacob,是另一个项目,现在已经比较陈旧,不推荐使用。

Apache POI for Office (特殊场景)

如果你调用的是 Microsoft Office 的 ActiveX 自动化接口(比如用 Java 控制 Excel),Apache POI 通常是更好的选择,POI 封装了复杂的 COM 调用,提供了更高级、更稳定的 API 来操作 Office 文档,而不是让你直接去调用底层的 COM 方法,POI 内部可能也使用了类似 Jacob 的技术,但它为开发者提供了更友好的接口。

商业解决方案 (如 J-Integra)

  • 优点:功能更强大,支持更复杂的情况,技术支持好。
  • 缺点:价格昂贵,对于大多数项目来说成本过高。

重要注意事项和局限性

  1. 平台限制:这是最关键的一点。ActiveX 是 Windows 独有的技术,任何使用 Jacob 调用 ActiveX 的 Java 程序,只能在 Windows 操作系统上运行,这在跨平台是硬伤。
  2. 位数匹配:JDK 的位数 (32/64) 必须与 Jacob DLL 的位数以及你调用的 ActiveX 控件的位数(在注册表中可见)完全一致,不匹配会导致 UnsatisfiedLinkError
  3. 线程问题:COM 组件不是线程安全的,Jacob 的文档建议,所有的 COM 调用都应该在同一个线程(通常是主线程或一个专门的 COM 线程)中进行,在 Swing 中,通常在 Event Dispatch Thread (EDT) 中进行初始化和操作是安全的。
  4. 依赖环境:目标机器上必须安装了你要调用的 ActiveX 控件,要调用 WebBrowser,目标机器上必须有 Internet Explorer。
  5. 错误处理:COM 调用可能会抛出各种 ComFailException,需要进行适当的异常捕获和处理。
方法 优点 缺点 适用场景
Jacob 开源、免费、简单、轻量 仅限 Windows、需要手动处理 DLL 绝大多数需要调用通用 ActiveX 的 Java 项目
Apache POI 高级 API、稳定、专为 Office 设计 不适用于通用 ActiveX,仅限 Office 文档操作 Java 程序需要自动化操作 Word, Excel, PowerPoint 时
商业方案 功能强大、支持好、稳定 价格昂贵 对稳定性和功能有极高要求的大型企业项目

对于绝大多数开发者来说,Jacob 是在 Java 中调用 ActiveX 控件的最佳和最实用的选择,请务必遵循其步骤,特别是关于 DLL 文件位数和放置位置的要求。

分享:
扫描分享到社交APP
上一篇
下一篇