首先说明的是,我所用的是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
#include
#include
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
#include
#include
#include "Platform.h"
#include "ui_axgm3ds.h"
class AxGm3ds : public QMainWindow, public QAxBindable
{
Q_OBJECT
public:
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_H
AxGm3ds.cpp
#include "axgm3ds.h"
#include
#include "../Application/launcher.h"
#include "objectsafetyimpl.h"
#include
#include
#include
#include "../AppEnv/sceneenv.h"
#include "../PlatformHolder/EventReceiver.h"
#include "../ServicesImp/CameraHelper.h"
#include "../CommonUtility/FileUtils.h"
#include
#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的网页了。话不多说,直接上代码:
"GENERATOR" Content="Microsoft Visual Studio">
定位权利人:type="text" name="editOwner">type="button" value="定位" onclick="locate(editOwner.value);">
分层分户:
type="button" value="第二层带线框" onclick="layerDoor(1, -1,true);">
type="button" value="第三层第二户" onclick="layerDoor(2, 1,false);">
type="button" value="重置" onclick="layerDoor(-1, -1,false);">
二维发送消息给三维:type="text" name="edit1" style="width:500px" value="示例数据"> type="button" value="发送" onclick="sendMessageTo3D(edit1.value);">
二维接收三维的消息:type="text" name="edit2" style="width:500px">
三维视点已变化:经度type="text" name="editLonCur"> 纬度type="text" name="editLatCur"> 高度type="text" name="editHeightCur">
设置三维视点:经度type="text" name="editLon"> 纬度type="text" name="editLat"> 高度type="text" name="editHeight">
type="button" value="设置" onclick="setCameraPos(117,45,0);">
<object id="ax" width="100%" height="96%" classid="CLSID:22F6B469-A701-4A1B-9CB2-8CD85C3021CD">object>
从这个JS的文件中,我告诉你们ActiveX是如何触发的,主要就是:
<object id="ax" width="100%" height="96%" classid="CLSID:22F6B469-A701-4A1B-9CB2-8CD85C3021CD">object>
要想触发ActiveX,需要在js文件中写,id也是必须的,classID是这个ActiveX的生成ID,这个东西在你建立一个ActiveX的时候,会自动生成,我上面的代码中有,你可以看看。
好了,我写的就是这么简单,希望对你们有帮助。