The OpenGL example demonstrates the use of the default factory and QAxFactory::isServer (), and the implementation of an additional COM interface using QAxBindable and QAxAggregated . The server executable can run both as an ActiveX server and as a stand-alone application.
此范例中的 ActiveX 控件使用 Qt QGlWidget 类在 ActiveX 中渲染 OpenGL 场景。控件暴露一些场景更改方法。
应用程序使用
QAxFactory
透过
QAXFACTORY_BEGIN()
,
QAXCLASS()
and
QAXFACTORY_END()
宏来暴露
GLBox
小部件作为 ActiveX 控制。
#include <QAxFactory> QAXFACTORY_BEGIN( "{2c3c183a-eeda-41a4-896e-3d9c12c3577d}", // type library ID "{83e16271-6480-45d5-aaf1-3f40b7661ae4}") // application ID QAXCLASS(GLBox) QAXFACTORY_END()
实现为
main
初始化
QApplication
对象,和使用
QAxFactory::isServer()
以确定创建和展示应用程序界面是否合适。
/* The main program is here. */ int main(int argc, char *argv[]) { QApplication a(argc,argv); if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGL) { qWarning("This system does not support OpenGL. Exiting."); return -1; } if (!QAxFactory::isServer()) { GLObjectWindow w; w.resize(400, 350); w.show(); return a.exec(); } return a.exec(); }
GLBox
类继承自两者
QOpenGLWidget
类为能够渲染 OpenGL,和
QAxBindable
.
#include <QAxBindable> class GLBox : public QOpenGLWidget, public QOpenGLFunctions_1_1, public QAxBindable { Q_OBJECT Q_CLASSINFO("ClassID", "{5fd9c22e-ed45-43fa-ba13-1530bb6b03e0}") Q_CLASSINFO("InterfaceID", "{33b051af-bb25-47cf-a390-5cfd2987d26a}") Q_CLASSINFO("EventsID", "{8c996c29-eafa-46ac-a6f9-901951e765b5}")
类重实现 QAxBindable::createAggregate () 函数从 QAxBindable 以返回指针指向 QAxAggregated 对象。
public: explicit GLBox(QWidget *parent, const char *name = nullptr); virtual ~GLBox(); QAxAggregated *createAggregate() override; public slots: void setXRotation(int degrees);
实现文件为
GLBox
类包括
objsafe.h
系统头,在那里
IObjectSafety
COM 接口有定义。
#include <objsafe.h>
类
ObjectSafetyImpl
的声明是使用多继承以子类化
QAxAggregated
类,并实现 IObjectSafety 接口。
class ObjectSafetyImpl : public QAxAggregated, public IObjectSafety { public:
类声明默认构造函数,并实现 queryInterface 函数以支持 IObjectSafety 接口。
explicit ObjectSafetyImpl() = default; long queryInterface(const QUuid &iid, void **iface) override { *iface = nullptr; if (iid != IID_IObjectSafety) return E_NOINTERFACE; *iface = static_cast<IObjectSafety*>(this); AddRef(); return S_OK; }
由于各 COM 接口继承
IUnknown
QAXAGG_IUNKNOWN
宏用于提供默认实现为
IUnknown
接口。宏定义将所有调用委托给
QueryInterface
,
AddRef
and
Release
到由 controllingUnknown() 函数返回的接口。
QAXAGG_IUNKNOWN;
实现为
IObjectSafety
接口为调用者提供支持和启用安全选项的有关信息,并返回
S_OK
为所有调用以指示 ActiveX 控件是安全的。
HRESULT WINAPI GetInterfaceSafetyOptions(REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions) override { Q_UNUSED(riid); *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) override { Q_UNUSED(riid); Q_UNUSED(pdwSupportedOptions); Q_UNUSED(pdwEnabledOptions); return S_OK; } };
实现为
createAggregate()
函数仅仅返回新
ObjectSafetyImpl
对象。
QAxAggregated *GLBox::createAggregate() { return new ObjectSafetyImpl(); }
要构建范例必须先构建
QAxServer
库。然后运行
qmake
和 make 工具在
examples/activeqt/wrapper
.
demonstration 要求 WebBrowser 支持 ActiveX 控件,并启用脚本。
相比其它 QAxServer 范例,Internet Explorer 不会打开对话框询问用户是否应该允许运行 GLBox 控件脚本 (浏览器的准确行为从属 "Internet 选项" 对话框中的安全设置)。
<SCRIPT LANGUAGE="JavaScript"> function setRot( form ) { GLBox.setXRotation( form.XEdit.value ); GLBox.setYRotation( form.YEdit.value ); GLBox.setZRotation( form.ZEdit.value ); } </SCRIPT> <p /> An OpenGL scene:<br /> <object ID="GLBox" CLASSID="CLSID:5fd9c22e-ed45-43fa-ba13-1530bb6b03e0" CODEBASE="http://qt.nokia.com/demos/openglax.cab"> [Object not available! Did you forget to build and register the server?] </object><br /> <form> Rotate the scene:<br /> X:<input type="edit" ID="XEdit" value="0" /><br /> Y:<input type="edit" name="YEdit" value="0" /><br /> Z:<input type="edit" name="ZEdit" value="0" /><br /> <input type="button" value="Set" onClick="setRot(this.form)" /> </form>