将GMap封装为Activex供QT使用(工具:VS2017,QT5.12)

由于一开始定的开发平台在QT下,到后面要加入地图控件.qt里本身带有地图qmap(在qt的官方案例中可以找到,用qml做的),但只有固定的几个地图源,要做google或者bing地图,时间和人力不允许,而且对地图也不是很熟悉..就决定先用gmap.

思路:

  gmap 是用c#开发的,像QT这种C++语言类无法直接使用,固将gmap 以com组件的形式封装成控件,供c++使用;

1.以管理员模式身份打开vs2017-文件-新建-项目-创建 Windows窗体控件库

框架可根据情况自行选择;   确定;

2.这时候就出现控件窗体了,可以更一下文件名

3. 工程属性设置    勾选 使程序集COM可见 ,勾选 为COM互操作可见 (其作用在于在程序编译后,不需要再安装com组件,如不是管理员身体启动vs,勾选它在编译时会报无权限错误)

4.添加gmap引用,我这里使用 NuGet 来添加....项目---管理NuGet程序包    浏览 搜索 gmap  点击 安装

5.安装完后 添加gmap控件到 控件窗体

  在工具箱 找到GmapControl 拖到控件窗体

  如果找不到 GmapControl  控件,, 需手动添加gmapcontrol控件

在工具箱空白处右键 打开 选择项    浏览到本项目解决方案下,有个packages 文件名,就是gmap的引用包,,浏览找到 GMap.NET.WindowsForms.dll 添加 即可.....这时工具箱内就会有GmapControl了

6.将 GmapControl 添加到窗体后,默认名为 gMapControl1  可自行更改 ..... 在  gMapControl1 控件上双击  添加以下代码

需添加引用

using GMap.NET.MapProviders;
using GMap.NET;

  

this.gMapControl1.CacheLocation = System.Windows.Forms.Application.StartupPath;//缓存文件路径
            this.gMapControl1.MapProvider = GMapProviders.BingHybridMap;
            this.gMapControl1.Manager.Mode = AccessMode.ServerAndCache;//地图模式为本地缓存,完全离线

            this.gMapControl1.ShowCenter = true;//隐藏或显示中心十字
            this.gMapControl1.MinZoom = 1;
            this.gMapControl1.MaxZoom = 23;
            this.gMapControl1.Zoom = 12;
            //this.gMapControl.ShowTileGridLines = false;//道路网格线
            this.gMapControl1.DragButton = System.Windows.Forms.MouseButtons.Left;//左健拖动地图
            this.gMapControl1.MouseWheelZoomType = MouseWheelZoomType.MousePositionWithoutCenter;//不以中心点缩放
            this.gMapControl1.Position = new PointLatLng(34.2313041, 108.8774211);

  

7,添加一个新的接口 IObjectSafety.cs

  代码如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices; //需手动添加的

namespace TestLibrary
{
    //以下代码可完全复制过去,不做任何改动,Guid 也不需要更改
    [ComImport, Guid("1D9AD540-F2C9-4368-8697-C4AAFCCE9C55")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IObjectSafety
    {
        [PreserveSig]
        int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);

        [PreserveSig()]
        int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);

    }
}

在AssemblyInfo.cs 文件中 添加  using System.Security;  和  [assembly: AllowPartiallyTrustedCallers()]

8,返回到  MapLibrary.cs , 给MapLibrary添加父类 IObjectSafety ,,,添加Guid (在工具--创建Guid   这个小工具里生成)

并添加代码

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using GMap.NET.MapProviders;
using GMap.NET;
using System.Runtime.InteropServices;

namespace TestLibrary
{
    [Guid("0E32CE01-4D40-45A6-8B59-B39ABFE8ADB0")]
    public partial class MapLibrary: UserControl, IObjectSafety //接口类的引用
    {
        public MapLibrary()
        {
            InitializeComponent();
        }

        private void gMapControl1_Load(object sender, EventArgs e)
        {

            this.gMapControl1.CacheLocation = System.Windows.Forms.Application.StartupPath;//缓存文件路径
            this.gMapControl1.MapProvider = GMapProviders.BingHybridMap;
            this.gMapControl1.Manager.Mode = AccessMode.ServerAndCache;//地图模式为本地缓存,完全离线

            this.gMapControl1.ShowCenter = true;//隐藏或显示中心十字
            this.gMapControl1.MinZoom = 1;
            this.gMapControl1.MaxZoom = 23;
            this.gMapControl1.Zoom = 12;
            //this.gMapControl.ShowTileGridLines = false;//道路网格线
            this.gMapControl1.DragButton = System.Windows.Forms.MouseButtons.Left;//左健拖动地图
            this.gMapControl1.MouseWheelZoomType = MouseWheelZoomType.MousePositionWithoutCenter;//不以中心点缩放
            this.gMapControl1.Position = new PointLatLng(34.2313041, 108.8774211);
        }

        #region IObjectSafety //以下 到 #endregion 为添加的代码,不需要做任何修改
        private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
        private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
        private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
        private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
        private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";

        private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
        private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
        private const int S_OK = 0;
        private const int E_FAIL = unchecked((int)0x80004005);
        private const int E_NOINTERFACE = unchecked((int)0x80004002);

        private bool _fSafeForScripting = true;
        private bool _fSafeForInitializing = true;

        public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
        {
            int Rslt = E_FAIL;

            string strGUID = riid.ToString("B");
            pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForScripting == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    Rslt = S_OK;
                    pdwEnabledOptions = 0;
                    if (_fSafeForInitializing == true)
                        pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }

        public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
        {
            int Rslt = E_FAIL;
            string strGUID = riid.ToString("B");
            switch (strGUID)
            {
                case _IID_IDispatch:
                case _IID_IDispatchEx:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
                        Rslt = S_OK;
                    break;
                case _IID_IPersistStorage:
                case _IID_IPersistStream:
                case _IID_IPersistPropertyBag:
                    if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
                        Rslt = S_OK;
                    break;
                default:
                    Rslt = E_NOINTERFACE;
                    break;
            }

            return Rslt;
        }
        #endregion

    }

}

9. 在Release 模式下编译生成 ,,成功后就生成 就可以封闭组件啦

10,生成activex控件.....在当前解决方案里添加一新项目 Setup Project    没有的自行百度解决..网上资料很多

添加工程后如下图,,在项目上  Add -- 项目输出     主输出   确定;

先点 下图的1 ,再点 2 的属性 ,,设置 3   Register为vsdrpCOM

编译生成!!!!  这时在项目目录下就会 有setup 两个文件...这时控件就生成了,,安装就可以使用..可以直接双击setup1.msi安装..也可以在项目上右键 安装/卸载

安装结束后 在注册表里可查看是否安装成功

以下是如何在QT中调用gMap

一.创建一个新的带窗口的QT工程

在pro 文件中添加配置   axcontainer ,  如下:

QT       += core gui axcontainer

重新qmake

添加头文件

#include <QAxWidget>

cpp中添加以下代码

#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QAxWidget>  //activex控件头文件

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QAxWidget * axWidget = new QAxWidget(this);
    axWidget->setControl(QString::fromUtf8("{0E32CE01-4D40-45A6-8B59-B39ABFE8ADB0}"));//这里的guid 就是在gmap中生成添加的guid..同时在注册表中也可以看到
   // axWidget->resize(620,720);
    axWidget->show();
}

MainWindow::~MainWindow()
{
    delete ui;
}

正常来说到这里就可以使用了,,但我这次为了写这个记录,顺便操作了一次,不知道是什么原因没有成功调用...

哪天我发现了再上来说明

封装过程参考:https://www.cnblogs.com/wyynts/p/6874387.html

原文地址:https://www.cnblogs.com/baqifanye/p/10414004.html

时间: 2024-08-28 01:22:36

将GMap封装为Activex供QT使用(工具:VS2017,QT5.12)的相关文章

第二章 Qt常用工具的介绍

(1)No.1 qmake 相信编写过Makefile的开发人员,随着工程中源码的级数递增和以类型.功能.模块组织源码的子目录的增多,都不愿意重复机械地手工编写这个工程管理文件.手写Makefile比较困难也容易出错.还没有编写过Makefile,甚至还不知道Makefile为何物的开发人员,也不用为此烦心,qmake可以方便地基于一个工程文件,生成不同平台下的Makefile.qmake关注编译器和处理器平台的依赖性,开发人员不用再手写针对不同编译器和不同处理器平台的Makefile,而可以花

Qt 5.14和Qt Creator工具简介

原文地址:https://blog.csdn.net/somken/article/details/104053605 Qt5简介Qt 5是Qt的最新版本.它使开发人员能够以直观的用户界面针对多个目标开发应用程序,这比以往任何时候都快.Qt 5可以更轻松地解决触摸屏和平板电脑所需的最新UI范式转换. 通过在Qt 5中改进对JavaScript和QML的支持,开发人员可以提高生产力和灵活性,同时仍具有C ++基础和Qt Widget支持.HTML5开发人员将对包含基于Chromium的Qt Web

vs2015添加ActiveX Control Test Container工具(转载)

http://blog.csdn.net/lphbtm/article/details/8647565 vs2010 中添加 ActiveX Control Test Container工具(转载) vs2010中的TSTCON( ActiveX Control Test Container )工具非自动安装,而是作为一个例程提供.所以应找到该例程,并编译: 如vs2010安装在默认路径则 1, 进入:C:\Program Files\Microsoft Visual Studio 10.0\S

vs2010添加TSTCON( ActiveX Control Test Container )工具

vs2010中的TSTCON( ActiveX Control Test Container )工具非自动安装,而是作为一个例程提供.所以应找到该例程,并编译: 如vs2010安装在默认路径则 1, 进入:C:\Program Files\Microsoft Visual Studio 10.0\Samples\1033,可找到VC2010Samples.zip文件, 2, 将其解决到同一个文件夹,解压后将出现一个C++子文件夹. 3, TstCon例程在:C:\Program Files\Mi

【Qt】Qt5.12连接MySQl5.7(亲自测试成功)

目录 00. 目录 01. Qt5.12连接MySQL5.7测试代码 02. Qt5.12连接MySQL5.7问题描述 03. 解决办法 04. 结果测试 05. 打赏 00. 目录 01. Qt5.12连接MySQL5.7测试代码 qDebug() << QSqlDatabase::drivers(); QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL"); db.setHostName("192.168.2

[ PyQt入门教程 ] Qt Designer工具的布局管理

这节课很重要..界面整洁美观与否就看布局了..这里讲布局方法,至于设计的天赋与最终界面的美感那就看造化了.. 本文主要讲述Qt Designer工具实现界面控件布局管理,就是排列组合控件.包括水平布局.垂直布局.网格布局.表单布局.至于绝对布局太复杂..短期内hold不住 布局管理打开方法 方法一:Qt Designer -> Form菜单栏 方法二:右键单击主窗口 -> Lay out 四种布局管理介绍 (1)水平布局 Lay Out Horizontally:被选中的控件在水平方向上从左到

【Qt】VS2010编译Qt5.3.2 64bit

讨论QQ群:135202158 1. 为什么要这么做 在Windows下,Qt官网默认提供的二进制版本大多是32位,目前(2015.01.24)只对VS2013提供了64位版本,如下图所示: 为了适应我目前安装的VS2010 IDE,也为了根据自己的需要编译特定的库和插件(比如去掉webkit之类),需要直接从源码编译Qt. 本例编译的是Qt5.3.2版本,应该也适用于Qt5.4.0. 2. 准备 首先,当然需要一个C++编译器,由于一些兼容性原因,我需要用Visual C++ 2010, 也可

Qt构建工具QBS之零 —— QBS 概览

本系列文章起因 自己非常喜欢 QT 这个框架, 使用 QT 这几年, IDE 一直是使用的 QT 自带的 Qt Creator, 这个 IDE 本身比较轻巧, 同事相关的语法提示之类的也算够用, 但是 qmake 有的时候就显得不那么只能了, 有时非得手动qmake一下才行, 有时需要清除再构建, 有时这两者合一起也不一定解决问题. 需要删除构建目录才行. 很多新手学习的时候, 经常会再论坛或群里问, 为什么我的代码和书上的一模一样, 怎么构建时就出错呢? 这种情况, 大多是 qmake “抽风

Qt——一些工具的使用

一.使用Qt需要安装哪些软件 如果不使用VS,那么只需Qt组件就行了,安装完成后使用QtCreator进行编程. 如果使用VS,则需要安装下面几个: 1.Visual Studio 2.Qt组件 3.VS的Qt插件 4.最好再安装一个VAssistX 二.VS中Qt插件的设置 配置环境—— 名称:随便起一个正常的名字,我的是QT5 路径:Qt的安装路径,我的是C:\Qt\Qt5.5.0\5.5\msvc2013 接下来打开工程设置,把版本改为上面设置的版本名称 三.VAssistX的设置 1.添