最近一直在用ActiveQt框架来写ActiveX插件, 由于项目需要提示类的导出, 所以上午捣鼓了一下, 现在记录记录.
其实内容主要是把Qt手册里自己用到的部分整理一下而已.
导出类的编写
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
用ActiveQt框架写导出类, 主要注意几点:
1. 派生关系
这里要注意必须要从QObject或它的派生类派生, 并且QObject要放在第一个. 也就是说, 如果你的类要从多个类派生的话, 必须写成这样:
.. code:: c++
class MyClass : public QObject, public MyBase
{
Q_OBJECT
......
};
2. 至少要写三个Q_CLASSINFO的宏
这里直接上代码吧, 写过ActiveX的应该都懂的:
.. code:: c++
Q_CLASSINFO("ClassID", "{60843C25-C9E9-4879-9FD1-9FFF60562DE0}")
Q_CLASSINFO("InterfaceID", "{FD3EB53C-E78A-468b-B776-9915B4224EB0}")
Q_CLASSINFO("EventsID", "{BFF922AB-4F38-435c-A190-FECCC6EE5041}")
这里的uuid可以用相关的功能生成, windows自带了, 我用的是``guidgen``.
3. 要保证与页面交互正常, 需要再从QAxBindable派生, 重写``QAxAggregated* createAggregate();``函数
重载这个接口, 是为了让IE认为你是安全的控件, 避免出现下面这个对话框:
.. image:: /galleries/ie.png
重载的函数也很简单:
.. code:: c++
QAxAggregated* ModelNode::createAggregate()
{
return new ObjectSafetyImpl;
}
这里的``ObjectSafetyImpl``是有点讲究, 不过在Qt的手册里也给出了这个类的标准写法, 直接照搬就可以, 这里给个范例:
.. code:: c++
#include <QAxAggregated>
#include <objsafe.h>
#include <QUuid>
class ObjectSafetyImpl : public QAxAggregated, public IObjectSafety
{
public:
ObjectSafetyImpl() {}
QAXAGG_IUNKNOWN;
long queryInterface( const QUuid &iid, void **iface )
{
*iface = 0;
if ( iid == IID_IObjectSafety )
*iface = (IObjectSafety*)this;
else
return E_NOINTERFACE;
AddRef();
return S_OK;
}
HRESULT WINAPI GetInterfaceSafetyOptions( REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions )
{
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER;
*pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA | INTERFACESAFE_FOR_UNTRUSTED_CALLER;
return S_OK;
}
HRESULT WINAPI SetInterfaceSafetyOptions( REFIID riid, DWORD pdwSupportedOptions, DWORD pdwEnabledOptions )
{
return S_OK;
}
};
用的时候, 把这个类保存为一个.h文件用就可以了.
**注意** 必须保存成.h, 不要把成员函数的实现再放到.cpp里, 因为这是一个模板类!!! *切记*
搞完上面的三步, 一个导出类就折腾得差不多了, 剩下的就是丰富一下这个类, 比如添加属性, 方法, 还有信号之类的.
类的导出
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
类搞完了, 就得导出不是. 这里用到的是``QAxFactory``, 不过咱这里不直接用这个类, 而是用它的几个宏就OK了.
.. code:: c++
QAXFACTORY_BEGIN(
"{F6D80CD5-446D-41DE-9859-F519FF49B970}",
"{435A18EC-4836-4EFD-8117-D6484752A6F8}")
QAXCLASS(ActiveOSG)
QAXCLASS(ModelNode)
QAXFACTORY_END()
这里的第一个uuid是typeid, 第二个是application id. 也都是ActiveX需要的东西
下面的东西就是我们要注意的, 这里ActiveQt框架提供了两个宏:
* ``QAXCLASS``
* ``QAXTYPE``
两者唯一的区别就是``QAXTYPE``导出的类不能直接创建, 只能用在导出类或函数的参数中, 也就是不能直接实例化.
所以在实际上, 我一般都是直接用``QAXCLASS``的.
小结
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
总的来说, ActiveQt框架用起来还是比直接写ActiveX插件来得爽快些, 需要注意的地方不多, 但代码就清爽多了.