qt之QActiveX

来源:互联网 发布:怎么设置网络防火墙 编辑:程序博客网 时间:2024/05/21 11:29

首先说明的是,我所用的是vs2013和qt5.3.1。
最近在做一个项目,是把三维地球整体放置到网页端,而这就需要用到了QT中的QActiveX。
对于QActiveX我们首要明白的一点是:它主要有两个模块:QAxContainer和QAxServer。对于这两个模块的分类,我有我自己的理解:先说QAxServer吧。
QAxServer:就相当于我新建立了一个ActiveX的项目,把这个三维的项目放置到这个ActiveX的项目里,然后封装成一个COM组件(也就是exe或者dlll);
QAxContainer:相当于我新建立了一个工程,把这个ActiveX组件加载到这个工程里来使用。

而对于我来说,我主要就是要把三维项目打包成ActiveX插件供网页端来使用。下面说说我实现的步骤:

1.新建一个Qt5的工程,选择菜单里面的ActiveQt Server这样就新建立了一个ActiveX的工程。

2.对于想要绕开安全验证的同志们,我们可以使用IObejctSafety来进行设置,具体的方法是:

virtual QAxAggregated * createAggregate();//这个虚方法是QAxBindable的虚方法,QAxBindable在工程建立的时候会自动生成。QAxAggregated * AxGm3ds::createAggregate(){    return new ObjectSafetyImpl;//ObjectSafetyImpl只需要一个头文件,我在下面已经写了}ObjectSafetyImpl.h#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;    }};

其实到这个时候,基本的功能都已经实现了,下面我把代码全都粘贴出来,依次为大家讲解,事先声明,我做的很简单。

AxGm3ds.h#ifndef AXGM3DS_H#define AXGM3DS_H#include <QtWidgets/QWidget>#include <ActiveQt/QAxBindable>#include <QMainWindow>#include "Platform.h"#include "ui_axgm3ds.h"class AxGm3ds : public QMainWindow, public QAxBindable{    Q_OBJECTpublic:    AxGm3ds(QWidget *parent = 0);    virtual QAxAggregated * createAggregate();signals:    //事件    void eventMessageOccurred(QString message);    void eventCameraPosChanged(double lon, double lat, double height);    //ActiveX供外界调用的方法--------------------------------------------------------------------    public slots:    //错误处理类    int Error_GetErrorCode();    QString Error_GetErrorMessage();    //向三维发送消息    void Common_SendMessage(QString message);    //相机操作类    void Camera_FlyTo(QString id);    void Camera_FlyToByRadian(double dLongitude, double dLatitude, double dHeight);    void Camera_FlyToByDegree(double dLongitude, double dLatitude, double dHeight);    //三维实体定位类    void Locating_LocateById(QString strId);    void Locating_LocateByFilter(QString strFilter);    //三维实体选择类    QString Selection_GetSelectedObjects();    QString Selection_GetSelectionByScreenPoint(int x, int y);    QString Selection_GetSelectionByScreenRect(int left, int top, int right, int bottom);    QString Selection_GetSelectionByFilter(QString strFilter);    void Selection_SelectObjectById(QString strId);    void Selection_SetSelectEffect(QString strSelectionEffect);    QString Selection_GetSelectEffect();    //漫游控制类    void Roaming_SetCurrentRoaming(QString strRoamingName,int nPathIndex);    void Roaming_Play();    void Roaming_Stop();    void Roaming_Pause();    //场景天空类    void Sky_SetDateTime(QString strDateTime);    void SKY_SetWeather(QString strWeatherType, int nTensity);    //场景地形类    void Terrain_SetTerrainOpacity(double dOpacity);    void Terrain_ModifyTerrainByRect(double dLeft, double dTop, double dRight, double dBottom, double dDepth);    void Terrain_ModifyTerrainByVertexes(QString strVertexesByRadian, double dDepth);    //系统Action调用类    void Action_Invoke(QString strActionName);    //End    private slots:    virtual void showEvent(QShowEvent *);    void onPlatformEvent(ea::IEventAdapter *pEventAdapter, ea::IEventObject *pEventObject);private:    void attachEventStub();private:    Ui::AxGm3dsClass ui;    bool m_bEventStubAttached;};#endif // AXGM3DS_HAxGm3ds.cpp#include "axgm3ds.h"#include <ActiveQt/QAxFactory>#include "../Application/launcher.h"#include "objectsafetyimpl.h"#include <QMainWindow>#include <iostream>#include <QMessageBox>#include "../AppEnv/sceneenv.h"#include "../PlatformHolder/EventReceiver.h"#include "../ServicesImp/CameraHelper.h"#include "../CommonUtility/FileUtils.h"#include <QDir>#include "../ServicesImp/CameraHelper.h"#include "../ServicesImp/ErrorHelper.h"#include "../ServicesImp/ObjectLocatingHelper.h"#include "../ServicesImp/ObjectSelectionHelper.h"#include "../ServicesImp/RoamingHelper.h"#include "../ServicesImp/SkyHelper.h"#include "../ServicesImp/SystemActionHelper.h"#include "../ServicesImp/TerrainHelper.h"AxGm3ds::AxGm3ds(QWidget *parent): QMainWindow(parent), m_bEventStubAttached(false){    Launcher::instance()->setApplicationEntryType(AET_WebBrowser);    Launcher::instance()->init(qApp);}//绕过安全验证QAxAggregated * AxGm3ds::createAggregate(){    return new ObjectSafetyImpl;}void AxGm3ds::attachEventStub(){    if (m_bEventStubAttached) return;    EventReceiver* reciever = SceneEnv::instance()->getEventReceiver();    if (!reciever) return;    connect(reciever, SIGNAL(signalEventOccurred(ea::IEventAdapter*, ea::IEventObject*)), this, SLOT(onPlatformEvent(ea::IEventAdapter*, ea::IEventObject*)));    m_bEventStubAttached = true;}void AxGm3ds::showEvent(QShowEvent *){    this->setCentralWidget(Launcher::instance()->action());    attachEventStub();}void AxGm3ds::onPlatformEvent(ea::IEventAdapter *pEventAdapter, ea::IEventObject *pEventObject){    if (pEventObject->getAction() == ea::ACTION_SCENE_INFO)    {        cmm::variant_data data;        pEventObject->getExtra("CameraCoord", data);        std::vector<double> point = data;        if (point.size() == 3)        {            emit eventCameraPosChanged(                cmm::math::Radians2Degrees(point[0]),                cmm::math::Radians2Degrees(point[1]),                cmm::math::Radians2Degrees(point[2]));        }    }}//Class:类//IIDClass:类ID的标识//IIDInterface:接口ID的标识//IIDEvents:事件ID的标识//IIDTypeLib:类型库的输出ID标识//IIDApp:QAXFACTORY_DEFAULT(AxGm3ds,    "{22F6B469-A701-4A1B-9CB2-8CD85C3021CD}",    "{48107DA9-41A3-4E61-BBA6-CD1933C89079}",    "{8D72F8C4-CCD3-46A7-B79C-CA9247327C4D}",    "{36548113-FB7A-4F75-9522-EB11995447D6}",    "{122099DF-8646-44F3-B718-E46559788B7E}")//-------------------------------------------------------ActiveX外部方法-----------------------------------------------------------------void AxGm3ds::Common_SendMessage(QString message){    QMessageBox::information(this, "ShowBy QtActiveX", QStringLiteral("收到外部消息:") + message);    //to do     emit eventMessageOccurred(QStringLiteral("消息[") + message + QStringLiteral("]处理完成"));}int AxGm3ds::Error_GetErrorCode(){    return ErrorHelper::getErrorType();}QString AxGm3ds::Error_GetErrorMessage(){    return ErrorHelper::getErrorMessage();}void AxGm3ds::Camera_FlyTo(QString id){    CameraHelper::flyTo(id);}void AxGm3ds::Camera_FlyToByRadian(double dLongitude, double dLatitude, double dHeight){    CameraHelper::flyToByRad(dLongitude, dLatitude, dHeight);}void AxGm3ds::Camera_FlyToByDegree(double dLongitude, double dLatitude, double dHeight){    CameraHelper::flyToByDegree(dLongitude, dLatitude, dHeight);}void AxGm3ds::Locating_LocateById(QString strId){    ObjectLocatingHelper::locatingById(strId);}void AxGm3ds::Locating_LocateByFilter(QString strFilter){    ObjectLocatingHelper::locatingByFilter(strFilter);}QString AxGm3ds::Selection_GetSelectedObjects(){    return ObjectSelectionHelper::getSelectedObjects();}QString AxGm3ds::Selection_GetSelectionByScreenPoint(int x, int y){    return ObjectSelectionHelper::getSelectionByScreenPoint(x, y);}QString AxGm3ds::Selection_GetSelectionByScreenRect(int left, int top, int right, int bottom){    return ObjectSelectionHelper::getSelectionByScreenRect(left, top, right, bottom);}QString AxGm3ds::Selection_GetSelectionByFilter(QString strFilter){    return ObjectSelectionHelper::getSelectionByFilter(strFilter);}void AxGm3ds::Selection_SelectObjectById(QString strId){    ObjectSelectionHelper::selectObjectById(strId);}void AxGm3ds::Selection_SetSelectEffect(QString strSelectionEffect){    ObjectSelectionHelper::setSelectEffect(strSelectionEffect);}QString AxGm3ds::Selection_GetSelectEffect(){    return ObjectSelectionHelper::getSelectEffect();}void AxGm3ds::Roaming_SetCurrentRoaming(QString strRoamingName,int nPathIndex){    RoamingHelper::setCurrentRoaming(strRoamingName,nPathIndex);}void AxGm3ds::Roaming_Play(){    RoamingHelper::play();}void AxGm3ds::Roaming_Stop(){    RoamingHelper::stop();}void AxGm3ds::Roaming_Pause(){    RoamingHelper::pause();}void AxGm3ds::Sky_SetDateTime(QString strDateTime){    SkyHelper::setDateTime(strDateTime);}void AxGm3ds::SKY_SetWeather(QString strWeatherType, int nTensity){    SkyHelper::setWeather(strWeatherType, nTensity);}void AxGm3ds::Terrain_SetTerrainOpacity(double dOpacity){    TerrainHelper::setTerrainOpacity(dOpacity);}void AxGm3ds::Terrain_ModifyTerrainByRect(double dLeft, double dTop, double dRight, double dBottom, double dDepth){    TerrainHelper::modifyTerrain(dLeft, dTop, dRight, dBottom, dDepth);}void AxGm3ds::Terrain_ModifyTerrainByVertexes(QString strVertexesByRadian, double dDepth){    TerrainHelper::modifyTerrain(strVertexesByRadian, dDepth);}void AxGm3ds::Action_Invoke(QString strActionName){    SystemActionHelper::invoke(strActionName);}

这样我们该写的都写了,下面我们就需要在网页中调用这个COM组件了,我所使用的是调用它的dll。在调用之前我们需要先把这个dll给注册了,注册的方法就是以管理员的身份打开命令窗口,输入regsvr32 C:\Users\Administrator\Documents\Visual Studio 2013\Projects\testActiveX\Win32\Debug\VShow.dll 我十分建议当我们输入dll的时候要用绝对路径,防止出现一些不必要的错误。同时,我需要提醒的是,这个dll依赖很多东西,我们选择的绝对路径,最好就是项目生成dll时候的那个路径,此外,当我们移动这个dll的位置的时候,我们需要重新注册,不然,你的浏览器是不可能打开的,对了,一定要使用IE浏览器,你可以试一下其它浏览器,会给你一个惊喜。

在注册完了之后,我们就要用JavaScript来写触发ActiveX的网页了。话不多说,直接上代码:

<HTML><HEAD><META NAME="GENERATOR" Content="Microsoft Visual Studio"><TITLE></TITLE> </HEAD><BODY>      定位权利人:<input type="text" name="editOwner"><input type="button" value="定位" onclick="locate(editOwner.value);">       分层分户:      <input type="button" value="第二层带线框" onclick="layerDoor(1, -1,true);">      <input type="button" value="第三层第二户" onclick="layerDoor(2, 1,false);">      <input type="button" value="重置" onclick="layerDoor(-1, -1,false);">      <br/>      二维发送消息给三维:<input type="text" name="edit1" style="width:500px" value="示例数据"> <input type="button" value="发送"  onclick="sendMessageTo3D(edit1.value);">       二维接收三维的消息:<input type="text" name="edit2" style="width:500px">      <br/>      三维视点已变化:经度<input type="text" name="editLonCur"> 纬度<input type="text" name="editLatCur"> 高度<input type="text" name="editHeightCur">      设置三维视点:经度<input type="text" name="editLon"> 纬度<input type="text" name="editLat"> 高度<input type="text" name="editHeight">      <input type="button" value="设置" onclick="setCameraPos(117,45,0);">      <!--<object id="ax" width="100%" height="96%" classid="CLSID:22F6B469-A701-4A1B-9CB2-8CD85C3021CD"></object>-->    <object id="ax" width="100%" height="96%" classid="CLSID:22F6B469-A701-4A1B-9CB2-8CD85C3021CD"></object>    <script type="text/javascript">        var axObject = document.getElementById('ax');        function sendMessageTo3D(message) {            axObject.Common_SendMessage(message);        }        function setCameraPos(lon, lat, height) {            axObject.Camera_FlyToByDegree(lon, lat, height);        }        function ax::cameraPosChanged(lon, lat, height) {            editLonCur.value = lon;            editLatCur.value = lat;            editHeightCur.value = height;        }    </script></BODY> </HTML>

从这个JS的文件中,我告诉你们ActiveX是如何触发的,主要就是:

    <object id="ax" width="100%" height="96%" classid="CLSID:22F6B469-A701-4A1B-9CB2-8CD85C3021CD"></object>

要想触发ActiveX,需要在js文件中写,id也是必须的,classID是这个ActiveX的生成ID,这个东西在你建立一个ActiveX的时候,会自动生成,我上面的代码中有,你可以看看。

好了,我写的就是这么简单,希望对你们有帮助。