将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互操作可见 (其作用在于在程序编译时,vs会自动将dll注册,如不是管理员身体启动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 = ;
this.gMapControl1.MaxZoom = ;
this.gMapControl1.Zoom = ;
//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 = ;
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 = ;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = ;
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 模式下编译生成 ,,成功后就生成 就可以封装组件啦
#start ################################################### 从此行到 #end ###之间为网上的教程,,没有测试成功,,,具体为什么还未知,,可能是还要再做一层接口封装,如有网友知道可留言
10,生成activex控件.....在当前解决方案里添加一新项目 Setup Project 没有的自行百度解决..网上资料很多

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


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

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

#end ############################################################
2019年3月15日更新 开始位置:
这里用的是我自己的工程,和之前更新的工程名和动态库名会不一样,,但意思是一样的...如不理解可留言...
在第9步 Release 编译结束后,,可以编译目录下找到 编译完成的dll文件夹 Release
将整个文件夹复制出来 这里我自己用的工程,,只保留dll,tlb,和x86,x64文件夹,放两个bat文件进去,代码如下
注册:
@echo off
set filename=gMapActiveX.dll
set Frameworkdc=%SystemRoot%\Microsoft.NET\Framework\v4.0.30319 if exist "%Frameworkdc%" goto netOld
:DispError
echo 您的机器上没有安装 .net Framework 4.0,安装即将终止.
goto LastEnd
:netOld
cd %Frameworkdc%
echo 您的机器上安装了相应的.net Framework 4.0,可以安装本服务.
echo 请输入回车确认安装:
PAUSE
rem %~dp0表示(bat文件)当前目录
%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe /codebase %~dp0\%filename%
PAUSE
反注册:
@echo off
set filename=gMapActiveX.dll
rem %~dp0表示(bat文件)当前目录
%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe /unregister %~dp0\%filename%
PAUSE
里面的filename需根据自己情况更改
这样只要将如下图的整个文件夹复制到任意一台电脑,,只要是有.net4.0的电脑,,以管理员运行注册,就可以将控件注册到注册表,,然后就可以调用了..
提示::整个过程有几点需要注意的,,如果gmap是以x64来编译的,那在调用的时候也必须要以64位程序来调用...反之用x86也一样..如果用any cpu 调用,理论上是可以64位和32位都可调用..
需要运行的机器有.net4.0
vs 勾选了 为com互操作后,vs就可以自动注册,,本开发机上就可随意调

2019年3月15日更新结束位置...............................................................
安装结束后 在注册表里可查看是否安装成功

以下是如何在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
将GMap封装为Activex供QT使用(工具:VS2017,QT5.12) 更新部署到其它电脑的更多相关文章
- 【Qt开发】vs2017+qt5.x编译32位应用
概述 最近有同学私信我,问如何使用vs2017+qt5.10编译出32位的应用,需要使用msvc2017_x86的插件,然而qt官网并没有提供,只能使用源码编译生成msvc2017_x86插件,使用n ...
- 麒麟系统开发笔记(二):国产麒麟系统搭建Qt开发环境安装Qt5.12
前言 开发国产应用,使用到银河麒麟V4,V10,本篇以V10记录,参照上一篇可安装V4.V7.V10三个版本,麒麟V4系自带了Qt,麒麟V10没有自带Qt,需要自己编译搭建环境. 银河麒麟V1 ...
- 第二章 Qt常用工具的介绍
第二章 Qt常用工具的介绍 (1)No.1 qmake 相信编写过Makefile的开发人员,随着工程中源码的级数递增和以类型.功能.模块组织源码的子目录的增多,都不愿意重复机械地手工编写这个工程管理 ...
- [ PyQt入门教程 ] Qt Designer工具的使用
Qt Designer是PyQt程序UI界面的实现工具,Qt Designer工具使用简单,可以通过拖拽和点击完成复杂界面设计,并且设计完成的.ui程序可以转换成.py文件供python程序调用.本文 ...
- 免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作简易流量爬虫
前言 我们之前的爬虫都是模拟成浏览器后直接爬取,并没有动态设置IP代理以及UserAgent标识,本文记录免费IP代理池定时维护,封装通用爬虫工具类每次随机更新IP代理池跟UserAgent池,并制作 ...
- 在Windows 环境下编译Qt静态库(QT5.32)
参考链接 Qt5.3 Tools and Versions MinGW ICU ActivePerl Qt 安装MinGW工具链环境 这里在Win32环境下要安装一个MinGW工具链,这里最好是先安装 ...
- vs2015添加ActiveX Control Test Container工具(转载)
http://blog.csdn.net/lphbtm/article/details/8647565 vs2010 中添加 ActiveX Control Test Container工具(转载) ...
- QT 5 安装 vs2017 后,出现找不到 rc.exe 问题
QT 5 安装 vs2017 后,出现找不到 rc.exe 问题 qt 5 cannot run 'rc.exe' 出现这种错误,是因为,rc.exe 未找到,也就是 SKD 路径不对. 找到相应的 ...
- C/C++ -- Gui编程 -- Qt库的使用 -- Qt5总结
主要变化: 1.与Qt4相比,Qt5可以直接显示中文不需要手工转码2.Qt5模块发生变化,大部分组件并入widgets模块 注意事项:工程文件加一句greaterThan(QT_MAJOR_VERSI ...
随机推荐
- SAAS是否能实现人在家工作的梦想?
在过去的十年,在人们的工作环境的巨大变化已经发生,越来越多的人选择在家工作. 高租金的办公室,络,快速宽带的广泛应用.这些因素都使得远程办公成为了人们工作中密不可分的一种方式.使用普通手机和办公操作系 ...
- 在实现视频播放器的步骤client(三)风行网络电影列表
(三) 今日热门电影实现这个功能.主要从server获取数据.然后显示在屏幕上.虽然说是从这个server获取电影信息数据,但,不实际的http相关知识,我们直接sdk包(56网络提供api),你将能 ...
- glibc内存管理方式
程序员接触的内存空间和系统接触的物理内存空间是有所区别的.对于一般进程来讲,他面对的是一个线性虚拟内存空间:地址从0到最大值.每一个进程面对的虚拟内存空间都是一样的,都享有全部的内存地址.虚拟内存空间 ...
- MVC 组件之间的关系
View和Controller都可以直接请求Model 但是Model不依赖View和controller lController可以直接请求View来显示具体页面 View不依赖Controller ...
- 基于树莓派的微型气象站设计与开发(Windows 10 IoT Core)
前言 树莓派(Raspberry Pi,RPi)是专门为学生计算机编程教育而设计,只有信用卡大小的卡片式电脑,可以运行Linux或者Windows 10 IoT Core操作系统.本文将利用树莓派和U ...
- ELINK编程器能用来做什么
以前 产品量产与测试的时候,在电脑上用JATG/SWD编程器或串口下载器等工具下载程序到产品中,效率低且操作复杂 现在 可以用ELINK脱机编程器来摆脱电脑并降低操作复杂度,只需把程序文件下载到 ...
- 微信小程序把玩(七)数据绑定
原文:微信小程序把玩(七)数据绑定 数据绑定有一部分前几个看着还行,后面的几个可能有几个不理解,界面展示的数据有的也因为条件没法显示.看不懂的可以先记着,后面真正用到时就会明白,反正我是这样想的.这里 ...
- WPF 调用API修改窗体风格实现真正的无边框窗体
原文:WPF 调用API修改窗体风格实现真正的无边框窗体 WPF中设置无边框窗体似乎是要将WindowStyle设置为None,AllowTransparency=true,这样才能达到WinForm ...
- Java程序员的现代RPC指南(Windows版预编译好的Protoc支持C++,Java,Python三种最常用的语言,Thrift则支持几乎主流的各种语言)
Java程序员的现代RPC指南 1.前言 1.1 RPC框架简介 最早接触RPC还是初学Java时,直接用Socket API传东西好麻烦.于是发现了JDK直接支持的RMI,然后就用得不亦乐乎,各种大 ...
- spring bean 加载过程(spring)
以classpathXmlApplication为例 入口方法包含3个部分, public ClassPathXmlApplicationContext(String[] configLocation ...