OpenGL 范例 (ActiveQt)

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>
					

范例工程 @ code.qt.io