COM是一种二进制兼容的接口,在windows平台上,可以使用任何的语言来通过COM调用。WORD在安装时已经在计算机上注册了相应的COM接口,理论上使用任意语言都可以调用其接口来生成WORD文档。

WORD的COM接口资料

有多种途径:

  1. 通过官方的VBA资料可以查看有哪些接口,可以尝试用C++使用。
  2. 用第三方工具dumpcpp可以直接将COM接口文件的接口导出成HTML
  3. 使用QT提供的内部接口,可以查询并导出相应的接口文件。

QT中使用

在QT中QAxObject对象表示一个COM接口对象。

查询COM接口对象所支持的方法和属性

调用COM对象QAxObject的方法generateDocumentation可以得到一个字符串描述的接口,可以将其输出到HTML文件中来查看。比如如下的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void QWord::createHtml(QString file, QAxObject *obj)
{
QFile htmlFile(file + ".html");
if(!htmlFile.exists())
{
if (htmlFile.open(QIODevice::WriteOnly | QIODevice::Text))
{
QString text = obj->generateDocumentation();
QTextStream txtOutput5(&htmlFile);
txtOutput5 << text << endl;
htmlFile.close();
}
}
}

调用COM接口对象的方法

可以使用dynamicCall 或者 querySubObject 来调用。两个方法的参数1都是对所调用的COM对象的方法原型描述,其后的都是各个参数,比如:

1
2
activeX->dynamicCall("Navigate(const QString&)", "www.qt-project.org");
activeX->querySubObject("Navigate(const QString&)", "www.qt-project.org");

这两个接口都可以达到调用方法的目的,他们的区别是一个返回QVariant对象,一个返回QAxOjbect指针。但是,QVarient也可以转换为QAxObject指针的。

另外dynamicCall调用时还可以有简写模式,比如前面的代码,可以简化为:

1
activeX->dynamicCall("Navigate(\"www.qt-project.org\")");

读COM接口对象的属性

推荐使用QObject::property的方法,因为QAxOjbect也是QObject的字类,这种方式是最高效的。

也可以使用dynamicCall和querySubObject来调用。代码如下:

1
2
QString text = activeX->dynamicCall("Text").toString();
m_word->querySubObject("Documents");

写COM接口对象的属性

推荐使用QObject::setProperty的方法,因为QAxOjbect也是QObject的字类,这种方式是最高效的。
也可以使用dynamicCall和querySubObject来调用。代码如下:

1
activeX->dynamicCall("Value", 5);

传参问题

如果接口参数过多的话,对于有默认值的参数,可以不必再dynamicCall函数中说明,直接忽略。比如有如下的接口:

1
"Open(QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&, QVariant&)"

在调用方法时,除去第1个,其它全部都有默认值,不是非必须的。因此,实际使用时可以根据需要来生命函数原型。比如如下的使用就是正确的。

1
documents->dynamicCall("Open (const QVariant&)", m_strFilePath);

总结建议

读写属性毫无疑问使用QObject的那套机制。函数调用,如果是方法的返回值是COM对象的话,建议使用querySubObject,如果方法无返回值或者返回非COM对象的话,建议使用dynamicCall。