一些比较关键的概念
COM(Component Object Model)
微软提出的一种技术,它定义了一种规范,通过COM可以轻松实现一种语言(如C#)调用另一种语言(如C++、VB等)开发的功能模块。
ActiveX
微软主要针对互联网客户端设计的,以上述COM为技术基础的一种实现。
两者的关系:
一般来说二者并没有本质的区别,仅有一些概念上的差异,一般来说:
- ActiveX一般包含一个窗体界面,COM对象一般并没有界面
- COM对象一般作为一个可调用的模块来使用,ActiveX一般嵌入在网页中使用
上述仅仅是一种使用上的惯例,但是并未强制一定这样
reference:Qt中使用ActiveX(一)
Qt中的COM支持:QtActiveX框架
Qt的ActiveX和COM的开发支持两种方式:
将已有的COM或者ActiveX空间引入到Qt的应用程序中
使用QAxContainer模块,通过QAxObject和QAxWidget分别支持COM对象和ActiveX控件的开发,可以通过这两个对象将外部的COM或者ActiveX组件接入到Qt应用程序
将Qt应用程序或者Qt的对象导出成COM对象或者ActiveX控件供他人使用
使用QAxServer模块,通过QAxAggregated、QAxBindable和QAxFactory类,通过了进程内和可执行程序exe两种方式的COM Server模式,用来将Qt写的内容导出为COM或者ActiveX供他人使用。
Qt中调用MicroSoft Word实践
1. 获取Word的COM对象
QAxObject word("Word.Application", 0);
“Word.Application” 是 Microsoft Word 应用程序的 ProgID (Programmatic Identifier),
它由 Microsoft Office 安装时注册到系统中,用于标识 Microsoft Word 应用程序的顶层 COM 对象。
通过这个 ProgID,QAxObject 可以创建并操控 Word 应用程序的实例。
可以使用 regedit
查看注册表中的 COM 类定义,路径通常是:
HKEY_CLASSES_ROOT\Word.Application
这表明 Windows 系统中注册了这个 COM 对象。
2. 用dynamicCall()
调用COM对象封装的方法
dynamicCall 是 QAxObject 类提供的一个方法,用于调用 COM 对象的接口函数。这些函数接口(如 “Add()”、“SaveAs()” 等)来源于 Microsoft Office 应用程序的 COM 接口,
具体的接口文档可以通过Microsoft Office开发者文档Word Object Model Reference查询。
dynamicCall 的使用
dynamicCall 方法通过字符串的形式接受 COM 接口的调用信息,格式类似于:
dynamicCall("MethodName(ArgumentType, ...)", argument1, argument2, ...);
其中:
"MethodName(...)"
是你要调用的 COM 接口方法名和参数类型。例如 "Add()"
、"SaveAs(const QString&)"
等。
后面的参数则是传递给 COM 方法的实际参数。
示例:
以SaveAs
方法为例,Documents
对象的 SaveAs
方法接受多个参数,包括文件路径、文件类型等:
复制代码
document->dynamicCall("SaveAs(const QString&, QVariant)", "C:\\path\\to\\file.docx", 16);
其中 "SaveAs(const QString&, QVariant)"
对应于 Word COM 接口中的 SaveAs
方法。
dynamicCall
函数可以接受 Qt 定义的变量类型(如 const QString&
),是因为 Qt 的 ActiveX/COM 框架(QAxObject
)内置了对常见 Qt 数据类型和 COM 数据类型的转换机制。
QAxObject
的类型转换层
处理 Qt 数据类型 和 COM 数据类型 之间的转换。COM 方法期望的参数通常是 Windows 原生类型(如 BSTR
、VARIANT
等),而 Qt 使用自己的数据类型(如 QString
、QVariant
等)。为了简化开发过程,Qt 自动处理了这些类型之间的转换。
在使用 dynamicCall 时,Qt 会将传入的参数转换为适合 COM 方法的格式,并且将 COM 返回的值转换回 Qt 的类型。这使得开发者能够直接使用 Qt 的数据类型与 COM 对象进行交互。
以下是一些常见的 Qt 类型和 COM 类型之间的映射关系:
1. QString → BSTR:
COM 中的字符串类型是 BSTR
,而 Qt 中的字符串是 QString
。Qt 提供了自动的字符串转换机制,将 QString
转换为 COM 可接受的 BSTR
。
当你在 dynamicCall
中传入一个 QString
时,Qt 会自动将它转换为 BSTR
,供 COM 方法使用。
如:
QString filePath = "C:\\path\\to\\file.docx";
document->dynamicCall("SaveAs(const QString&)", filePath);
在内部,Qt 会将 filePath
转换为 BSTR
类型的字符串。
2. QVariant → VARIANT:
COM 中的 VARIANT
类型可以表示多种数据类型,如整数、浮点数、字符串等。Qt 的 QVariant
是一个类似的容器类,能够存储多种类型的数据。
当你在 dynamicCall
中传入 QVariant
类型的参数时,Qt 会自动将它转换为相应的 VARIANT
类型。
3. int、double → int、double:
基础类型,如 int 和 double,在 Qt 和 COM 之间能够直接映射,因此不需要复杂的转换。
例如,在 COM 方法中需要一个整数参数时,Qt 的 int 类型会自动转换为 COM 可识别的整数类型。
4. QList、QMap → SAFEARRAY:
SAFEARRAY
是 COM 中用于表示数组的类型。如果你需要传递一个数组,Qt 可以将 QList 或 QMap 转换为 SAFEARRAY。
类型转换的实现原理:
Qt 通过 QVariant
和 ActiveQt
库实现了这种自动类型转换。QVariant
是一个能够容纳多种类型的类,它能够自动处理 Qt 内部类型与 Windows COM 类型之间的转换。
QAxObject::dynamicCall
会检查传入参数的类型,并根据类型调用适当的转换函数,将 Qt 类型转换为对应的 COM 类型。
这种类型转换机制是由 ActiveQt
库(Qt 提供的与 ActiveX 和 COM 交互的模块)负责的。ActiveQt
自动处理了许多常见类型的转换,因此开发者在使用 QAxObject
与 COM 交互时,通常不需要手动处理类型转换。