最近需要用到esri 的ActiveX控件MapObjects.刚开始以为Qt不支持MapObjects,因为在网上查了好多Qt+MapObjects关键字搜索不到相关的资料。后来在Qt里面加了个QAxWidget,然后设置控件,发现列表里有MapObjects控件,所以Qt应该是支持MapObjects的(我的开发环境是vs2010+Qt4.8.4)。下面关于QAxWidget和MapObjects 进行简单的介绍:(参考:点击打开链接)
1.QAxWidget的使用
在vs2010中新建一个Qt工程,命名为MOtest,在MOtest类的构造函数中添加如下代码:
MOtest::MOtest(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QAxWidget *mmap = new QAxWidget(this ,0);
this->resize(500, 500);
mmap->resize(500, 500);
mmap->setControl(QString::fromUtf8("{d27cdb6e-ae6d-11cf-96b8-444553540000}"));//flash的CLSID
mmap->dynamicCall("LoadMovie(long,string)",0,"F:/test.swf");
mmap->show();
}
运行程序会在一个窗口中播放flash文件 F:/test.swf
2.MapObjects在QAxWidget中使用
修改上面的构造函数,首先尝试添加一些简单的函数看看MapObjects控件能不能正常使用:
MOtest::MOtest(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
QAxWidget *mmap = new QAxWidget(this ,0);
this->resize(500, 500);
mmap->resize(500, 500);
mmap->setControl(QString::fromUtf8("{9BD6A64B-CE75-11D1-AF04-204C4F4F5020}"));//MapObjects组件的CoClassID
QVariantList params;//参数链表
QColor color(85, 135, 206);
// QString text("map objects test!");
params.push_back(color);
// params.push_back(text);
params.push_back(1);
mmap->dynamicCall("SetBackColor(QColor)", params.at(0));//设置Map控件的背景颜色
mmap->dynamicCall("SetBorderStyle(int)", params.at(1));//设置Map控件的边框是否可见
}
在Qt里QAxWidget的使用基本就通过建立一个空的COM组件对象,然后在把需要封装的组件放到对象中。代码就是上面的new和setControl两个操作。解决了导入的问题,接下来就是如何使用该组件的接口和方法。COM是个自描述的结果,任何第三方软件都可以把这种描述化信息自动导出来。Qt中导出方法:
QString doc=mmap->generateDocumentation();
QFile outFile("F:/MapObjects.html");
outFile.open(QIODevice::WriteOnly|QIODevice::Append);QTextStream ts(&outFile);
ts<<doc<<endl;
得到的html文档里面包含有MapObjects在Qt下的一些接口和方法、属性。参考里面的帮助就可以调用函数了。
QVariantList params0;
params0<<QVariant((int)(w.winId()));
params0<<QVariant(1);
params0<<QVariant("License");
params0<<QVariant("");
object.dynamicCall("ShowStatusDialog(int,int,QVariant,QVariant)",params0);
从上面代码可以看出,可以通过dynamicCall方法来调用ActiveX控件的方法。有些注意的地方:(参考:点击打开链接)
1)dynamicCall()最多传递八个QVariant类型的参数,并且返回类型也是QVariant。
2)如果我们需要传递IDispatch *或者是IUnknown *,我们可以将这些组件封装成QAxObject,然后通过调用asVariant()方法来将这个COM对象转换为QVariant。同样如果我们返回一个IDispatch*或者IUnknown*的对象,就需要通过querySubObject方法将这个对象转换为QAxObject。
QAxObject *session = outlook.querySubObject("Session");
3)如果不想这样做还可以QAxWidget还为我们提供了QueryInterface方法
IWebBrowser2 *webBrowser = 0;
activeX->queryInterface(IID_IWebBrowser2, (void *)&webBrowser);
if (webBrowser) {
webBrowser->Navigate2(pvarURL);
webBrowser->Release();
}
4)dynamicCall方法还可以设置COM控件的属性:
activeX->dynamicCall("Value", 5);
QString text = activeX->dynamicCall("Text").toString();
5)通过dynamicCall调用COM对象的方法的时候需要提供完成的函数签名。
activeX->dynamicCall("Navigate(const QString&)", "qt.nokia.com");