vb.net 将 Google 地图添加到 VB 2010 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9451954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 15:58:27  来源:igfitidea点击:

Adding Google Maps to a VB 2010 application

vb.netwinformsgoogle-maps

提问by user1145581

I want to write a Windows Forms application in VB 2010 that will allow the user to search and view addresses or coordinate points on Google Maps. I've already done this by using a WebBrowser item. However I want to use a wrapper so that I can just display the map to the user, but still be able to move and zoom the map or give directions, etc. I know there are ways to do this when developing an ASP.NET site, but I want to do this for a WindowsForms app. Could anyone please help?

我想在 VB 2010 中编写一个 Windows 窗体应用程序,它允许用户在 Google 地图上搜索和查看地址或坐标点。我已经通过使用 WebBrowser 项完成了此操作。但是我想使用一个包装器,以便我可以只向用户显示地图,但仍然能够移动和缩放地图或给出方向等。我知道在开发 ASP.NET 站点时有一些方法可以做到这一点,但我想为 WindowsForms 应用程序执行此操作。有人可以帮忙吗?

采纳答案by Alex

Google Maps API for .NET seeme to be what you are looking for

适用于 .NET 的 Google Maps API 似乎正是您要找的

http://gmaps.codeplex.com/

http://gmaps.codeplex.com/

from the site

从网站

This project intends to provide all the features available in the Google Maps API. It is being developed in C# for .NET Framework 3.5.

该项目旨在提供 Google Maps API 中可用的所有功能。它正在用 C# 为 .NET Framework 3.5 开发。

Although the project is in C# you can probably just add a reference to the project and use it just like any other reference and write your code in any CLR compliant languege , including VB.

尽管该项目是在 C# 中,但您可能只需添加对该项目的引用并像任何其他引用一样使用它,并以任何 CLR 兼容语言(包括 VB)编写您的代码。

回答by Carlos Borau

Probably too late, but I recently had to deal with google maps in vb and wanted to share my solution:

可能太晚了,但我最近不得不在 vb 中处理谷歌地图并想分享我的解决方案:

The first part of this example explains how to implement it. In the second, I will explain how it works. This tries to be a general example. The template for the map (see step 3) and the example functions are fully customizable.

这个例子的第一部分解释了如何实现它。在第二部分,我将解释它是如何工作的。这试图成为一个普遍的例子。地图模板(参见第 3 步)和示例函数是完全可定制的。

################################# IMPLEMENTATION ############################

################################# 执行 ################ #############

Step 1.Firstly, create a new project and select Windows Form Application. Let's leave its name as "Form1".

步骤 1.首先,创建一个新项目并选择 Windows Form Application。让我们将其名称保留为“Form1”。

enter image description here

在此处输入图片说明

Step 2.Add a WebBrowser control (which will hold your map) to your Form1. Let's call it "wbmap"

步骤 2.将 WebBrowser 控件(将保存您的地图)添加到您的 Form1。我们称之为“wbmap”

Step 3.Create a .html file named "googlemap_template.html" with your favourite text editor and paste the following code:

第 3 步。使用您喜欢的文本编辑器创建一个名为“googlemap_template.html”的 .html 文件并粘贴以下代码:

googlemap_template.html

googlemap_template.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <style type="text/css">
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      #gmap {
        height: 100%;
      }
     </style>
    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
    <script type="text/javascript">
        function initialize() {
            //Use window.X instead of var X to make a variable globally available 
            window.markers = new Array();
            window.marker_data = [[MARKER_DATA]];
            window.gmap = new google.maps.Map(document.getElementById('gmap'), {
            zoom: 15,
            center: new google.maps.LatLng(marker_data[0][0], marker_data[0][1]),
            mapTypeId: google.maps.MapTypeId.ROADMAP
          });
          var infowindow = new google.maps.InfoWindow();
          var newmarker, i;
          for (i = 0; i < marker_data.length; i++) {
              if (marker_data[0].length == 2) {
                  newmarker = new google.maps.Marker({
                      position: new google.maps.LatLng(marker_data[i][0], marker_data[i][1]),
                      map: gmap
                  });
              } else if (marker_data[0].length == 3) {
                  newmarker = new google.maps.Marker({
                      position: new google.maps.LatLng(marker_data[i][0], marker_data[i][1]),
                      map: gmap,
                      title: (marker_data[i][2])
                  });
              } else {
                  newmarker = new google.maps.Marker({
                      position: new google.maps.LatLng(marker_data[i][0], marker_data[i][1]),
                      map: gmap,
                      title: (marker_data[i][2]),
                      icon: (marker_data[i][3])
                  });
              }
            google.maps.event.addListener(newmarker, 'click', (function (newmarker, i) {
                return function () {
                    if (newmarker.title) {
                        infowindow.setContent(newmarker.title);
                        infowindow.open(gmap, newmarker);
                    }
                    gmap.setCenter(newmarker.getPosition());
                    // Calling functions written in the WF
                    window.external.showVbHelloWorld();
                    window.external.getMarkerDataFromJavascript(newmarker.title,i);
                }
            })(newmarker, i));
            markers[i] = newmarker;
          }
        }
        google.maps.event.addDomListener(window, 'load', initialize);
    </script>
    <script type="text/javascript">
        // Function triggered from the WF with no arguments
        function showJavascriptHelloWorld() {
            alert("Hello world in HTML from WF");
        }
     </script>
      <script type="text/javascript">
        // Function triggered from the WF with a String argument
        function focusMarkerFromIdx(idx) {
            google.maps.event.trigger(markers[idx], 'click');
        }
      </script>
  </head>
  <body>
    <div id="gmap"></div>
  </body>
</html>

This will serve as our map template. I will explain how it works later.

这将作为我们的地图模板。稍后我将解释它是如何工作的。

Step 4.Add the googlemap_template.hmtl file to your project (right click on your project->add->existing item)

第 4 步。将 googlemap_template.hmtl 文件添加到您的项目中(右键单击您的项目->添加->现有项目)

Step 5.Once it appears in your Solution Explorer, set its properties to: - Build Action -> Embedded Resource - Custom Tool Namespace -> write the name of the project

第 5 步。一旦它出现在您的解决方案资源管理器中,将其属性设置为: - 构建操作 -> 嵌入式资源 - 自定义工具命名空间 -> 写入项目名称

enter image description here

在此处输入图片说明

Step 6.Add a new class (right click on your project->add->class). In my example I'll call it GoogleMapHelper.

步骤 6.添加一个新类(右键单击您的项目->添加->类)。在我的示例中,我将其称为 GoogleMapHelper。

enter image description here

在此处输入图片说明

Step 7.Paste the following code into your class:

步骤 7.将以下代码粘贴到您的类中:

GoogleMapHelper.vb

谷歌地图助手.vb

    Imports System.IO
    Imports System.Reflection
    Imports System.Text

    Public Class GoogleMapHelper

    ' 1- googlemap_template.html must be copied in the main project folder
    ' 2- add the file into the Visual Studio Solution Explorer (add existing file)
    ' 3- set the properties of the file to: 
    '                                   Build Action -> Embedded Resource
    '                                   Custom Tool Namespace -> write the name of the project

    Private Const ICON_FOLDER As String = "marker_icons/" 'images must be stored in a folder inside  Debug/Release folder
    Private Const MAP_TEMPLATE As String = "WindowsApplication1.googlemap_template.html"
    Private Const TEXT_TO_REPLACE_MARKER_DATA As String = "[[MARKER_DATA]]"
    Private Const TMP_NAME As String = "tmp_map.html"


    Private mWebBrowser As WebBrowser

    'MARKER POSITIONS 
    Private mPositions As Double(,) 'lat, lon
    ' marker data allows different formats to include lat,long and optionally title and icon:
    ' op1: mMarkerData = New String(N-1, 1) {{lat1, lon1}, {lat2, lon2}, {latN, lonN}} 
    ' op2: mMarkerData = New String(N-1, 2) {{lat1, lon1,'title1'}, {lat2, lon2,'title2'}, {latN, lonN, 'titleN'}} 
    ' op3: mMarkerData = New String(N-1, 3) {{lat1, lon1,'title1','image1.png'}, {lat2, lon2,'title2','image2.png'}, {latN, lonN, 'titleN','imageN.png'}} 
    Private mMarkerData As String(,) = Nothing


    Public Sub New(ByRef wb As WebBrowser, pos As Double(,))
        mWebBrowser = wb
        mPositions = pos
        mMarkerData = getMarkerDataFromPositions(pos)
    End Sub

    Public Sub New(ByRef wb As WebBrowser, md As String(,))
        mWebBrowser = wb
        mMarkerData = md
    End Sub

    Public Sub loadMap()
        mWebBrowser.Navigate(getMapTemplate())
    End Sub

    Private Function getMapTemplate() As String

        If mMarkerData Is Nothing Or mMarkerData.GetLength(1) > 4 Then
            MessageBox.Show("Marker data has not the proper size. It must have 2, 3 o 4 columns")
            Return Nothing
        End If

        Dim htmlTemplate As New StringBuilder()
        Dim tmpFolder As String = Environment.GetEnvironmentVariable("TEMP")
        Dim dataSize As Integer = mMarkerData.GetLength(1) 'number of columns
        Dim mMarkerDataAsText As String = String.Empty
        Dim myresourcePath As String = My.Resources.ResourceManager.BaseName
        Dim myresourcefullPath As String = Path.GetFullPath(My.Resources.ResourceManager.BaseName)
        Dim localPath = myresourcefullPath.Replace(myresourcePath, "").Replace("\", "/") & ICON_FOLDER

        htmlTemplate.AppendLine(getStringFromResources(MAP_TEMPLATE))
        mMarkerDataAsText = "["

        For i As Integer = 0 To mMarkerData.GetLength(0) - 1
            If i <> 0 Then
                mMarkerDataAsText += ","
            End If
            If dataSize = 2 Then 'lat,lon
                mMarkerDataAsText += "[" & mMarkerData(i, 0) & "," + mMarkerData(i, 1) & "]"
            ElseIf dataSize = 3 Then 'lat,lon and title
                mMarkerDataAsText += "[" & mMarkerData(i, 0) & "," + mMarkerData(i, 1) & ",'" & mMarkerData(i, 2) & "']"
            ElseIf dataSize = 4 Then 'lat,lon,title and image
                mMarkerDataAsText += "[" & mMarkerData(i, 0) & "," + mMarkerData(i, 1) & ",'" & mMarkerData(i, 2) & "','" & localPath & mMarkerData(i, 3) & "']" 'Ojo a las comillas simples en las columnas 3 y 4 
            End If
        Next

        mMarkerDataAsText += "]"
        htmlTemplate.Replace(TEXT_TO_REPLACE_MARKER_DATA, mMarkerDataAsText)

        Dim tmpHtmlMapFile As String = (tmpFolder & Convert.ToString("\")) + TMP_NAME
        Dim existsMapFile As Boolean = False
        Try
            existsMapFile = createTxtFile(tmpHtmlMapFile, htmlTemplate)
        Catch ex As Exception
            MessageBox.Show("Error writing temporal file", "Writing Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
        End Try

        If existsMapFile Then
            Return tmpHtmlMapFile
        Else
            Return Nothing
        End If
    End Function

    Private Function getMarkerDataFromPositions(pos As Double(,)) As String(,)
        Dim md As String(,) = New String(pos.GetLength(0) - 1, 1) {}
        For i As Integer = 0 To pos.GetLength(0) - 1
            md(i, 0) = pos(i, 0).ToString("g", New System.Globalization.CultureInfo("en-US"))
            md(i, 1) = pos(i, 1).ToString("g", New System.Globalization.CultureInfo("en-US"))
        Next
        Return md
    End Function

    Private Function getStringFromResources(resourceName As String) As String
        Dim assem As Assembly = Me.[GetType]().Assembly

        Using stream As Stream = assem.GetManifestResourceStream(resourceName)
            Try
                Using reader As New StreamReader(stream)
                    Return reader.ReadToEnd()
                End Using
            Catch e As Exception
                Throw New Exception((Convert.ToString("Error de acceso al Recurso '") & resourceName) + "'" & vbCr & vbLf + e.ToString())
            End Try
        End Using
    End Function

    Private Function createTxtFile(mFile As String, content As StringBuilder) As Boolean
        Dim mPath As String = Path.GetDirectoryName(mFile)
        If Not Directory.Exists(mPath) Then
            Directory.CreateDirectory(mPath)
        End If
        If File.Exists(mFile) Then
            File.Delete(mFile)
        End If
        Dim sw As StreamWriter = File.CreateText(mFile)
        sw.Write(content.ToString())
        sw.Close()
        Return True
    End Function
    End Class

Note:The MAP_TEMPLATE constant must include the name of your project

注意:MAP_TEMPLATE 常量必须包含您的项目名称

Step 8.Now we can use our GoogleMapHelper class to load the map into our webbrowser by simply creating and instance and calling its loadMap() method. How you build your markerData is up to you. In this example, for clarification, I write them by hand. There are 3 options to define the marker data (see GoogleMapHelper class comments). Note that if you use the third option (including title and icons) you must create a folder called "marker_icons" (or whatever you define in the GoogleMapHelper constant ICON_FOLDER) in your Debug/Release folder and place there your .png files. In my case:

第 8 步。现在我们可以使用我们的 GoogleMapHelper 类通过简单地创建和实例并调用它的 loadMap() 方法来将地图加载到我们的网络浏览器中。您如何构建标记数据取决于您。在这个例子中,为了澄清起见,我手写了它们。有 3 个选项可以定义标记数据(请参阅 GoogleMapHelper 类注释)。请注意,如果您使用第三个选项(包括标题和图标),您必须在您的 Debug/Release 文件夹中创建一个名为“marker_icons”(或您在 GoogleMapHelper 常量 ICON_FOLDER 中定义的任何内容)的文件夹,并将您的 .png 文件放在那里。就我而言:

enter image description here

在此处输入图片说明

I created two buttons in my Form1 to illustrate how the map and the WF interact. Here is how it looks:

我在 Form1 中创建了两个按钮来说明地图和 WF 如何交互。这是它的外观:

enter image description here

在此处输入图片说明

And here is the code:

这是代码:

Form1.vb

表格1.vb

Imports System.IO
Imports System.Reflection
Imports System.Security.Permissions
Imports System.Text
<PermissionSet(SecurityAction.Demand, Name:="FullTrust")>
<System.Runtime.InteropServices.ComVisible(True)>
Public Class Form1

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

    Me.wbmap.ObjectForScripting = Me

    Dim onlyPositions As Double(,) = New Double(2, 1) {{42.13557, -0.40806}, {42.13684, -0.40884}, {42.13716, -0.40729}}
    Dim positonAndTitles As String(,) = New String(2, 2) {{"42.13557", "-0.40806", "marker0"}, {"42.13684", "-0.40884", "marker1"}, {"42.13716", "-0.40729", "marker2"}}
    Dim positonTitlesAndIcons As String(,) = New String(2, 3) {{"42.13557", "-0.40806", "marker0", "truck_red.png"}, {"42.13684", "-0.40884", "marker1", "truck_red.png"}, {"42.13716", "-0.40729", "marker2", "truck_red.png"}}

    'Dim gmh As GoogleMapHelper = New GoogleMapHelper(wbmap, onlyPositions)
    'Dim gmh As GoogleMapHelper = New GoogleMapHelper(wbmap, positonAndTitles)
    Dim gmh As GoogleMapHelper = New GoogleMapHelper(wbmap, positonTitlesAndIcons)
    gmh.loadMap()
End Sub

'############################### CALLING JAVASCRIPT METHODS ##############################
'This methods call methods written in googlemap_template.html
Private Sub callMapJavascript(sender As Object, e As EventArgs) Handles Button1.Click
    wbmap.Document.InvokeScript("showJavascriptHelloWorld")
End Sub

Private Sub callMapJavascriptWithArguments(sender As Object, e As EventArgs) Handles Button2.Click
    wbmap.Document.InvokeScript("focusMarkerFromIdx", New String() {2})
End Sub
'#########################################################################################

'############################### METHODS CALLED FROM JAVASCRIPT ##########################
'This methods are called by the javascript defined in googlemap_template.html when some events are triggered
Public Sub getMarkerDataFromJavascript(title As String, idx As String)
    MsgBox("Title: " & title & " idx: " & idx)
End Sub

Public Sub showVbHelloWorld()
    MsgBox("Hello world in WF from HTML")
End Sub
End Class

IMPORTANT :don't forget to add these lines before your class Form1 definition:

重要提示:不要忘记在类 Form1 定义之前添加这些行:

<PermissionSet(SecurityAction.Demand, Name:="FullTrust")>
<System.Runtime.InteropServices.ComVisible(True)>

What they do is to tell the .NET Framework that we want fulltrust and make the class visible to COM so Form1 is visible to JavaScript.

他们所做的是告诉 .NET Framework 我们想要完全信任并使类对 COM 可见,因此 Form1 对 JavaScript 可见。

Also don't forget this in your Form1 load function:

也不要在 Form1 加载函数中忘记这一点:

Me.wbmap.ObjectForScripting = Me

It exposes your Form1 class to the JavaScript on the googlemap_template.hmtl page.

它向 googlemap_template.hmtl 页面上的 JavaScript 公开您的 Form1 类。

Now you can execute and it should be working

现在你可以执行,它应该可以工作

################################# HOW IT WORKS#################################

################################# 这个怎么运作############## ###################

Basically, what our GoogleMapHelper class does is to read our googlemap_template.html, make a temporal copy, replace the code related to the markers ([[MARKER_DATA]]) and execute the page in the web browser control of our form. This html loops through all the markers and assigns a 'click' listener to each one. This click function is obviously fully customizable. In the example it opens an infowindow if the marker has a title, centers the map in such marker and calls two external functions that are defined in our Form1 class.

基本上,我们的 GoogleMapHelper 类所做的是读取我们的 googlemap_template.html,制作一个临时副本,替换与标记相关的代码 ([[MARKER_DATA]]) 并在我们表单的 Web 浏览器控件中执行页面。此 html 遍历所有标记并为每个标记分配一个“点击”侦听器。这个点击功能显然是完全可定制的。在示例中,如果标记有标题,它会打开一个信息窗口,将地图居中放置在这样的标记中,并调用在我们的 Form1 类中定义的两个外部函数。

On the other hand, we can define other javascript functions (with or without arguments) in this html to be called from our Windows Form (by using wbmap.Document.InvokeScript).

另一方面,我们可以在此 html 中定义其他 javascript 函数(带或不带参数)以从我们的 Windows 窗体(通过使用 wbmap.Document.InvokeScript)调用。

回答by Steve

I have use this control and it's really fantastic. It let you use not only GoogleMaps but virtually all the major mapping services, however, the last time I have checked, they have got some licensing troubles with google.

我使用过这个控件,它真的很棒。它让您不仅可以使用 GoogleMaps,还可以使用几乎所有主要的地图服务,但是,我上次检查时,他们在 google 方面遇到了一些许可问题。

GreatMaps on codeplex

Codeplex 上的 GreatMaps

回答by Tanmay Nehete

Try this code to get direction between two location

试试这个代码来获取两个位置之间的方向

Dim queryaddress As New System.Text.StringBuilder
        Dim sStreet As String = String.Empty
        Dim sCity As String = String.Empty
        Dim sState As String = String.Empty
        Dim sPincode As String = String.Empty
        Dim sProvider_no As String = String.Empty
        queryaddress.Append("https://www.google.com/maps/dir/")

        If txtprovider_no.Text <> "" Then
            sProvider_no = txtprovider_no.Text.Replace(" ", "+")
            queryaddress.Append(sProvider_no + "," & "+")
        End If
        If txtState.Text <> "" Then
            sState = txtState.Text.Replace("  ", "+")
            queryaddress.Append(sState + "," & "+")
        End If
        If txtCity.Text <> "" Then
            sCity = txtCity.Text.Replace("  ", "+")
            queryaddress.Append(sCity + "," & "+")
        End If
        If txtPincode.Text <> "" Then
            sPincode = txtPincode.Text.Replace("  ", "+")
            queryaddress.Append(sPincode)
        End If

        queryaddress.Append("/")
        sStreet = String.Empty
        sCity = String.Empty
        sState = String.Empty
        sPincode = String.Empty
        If txtlindmark.Text <> "" Then
            sStreet = txtlindmark.Text.Replace("  ", "+")
            queryaddress.Append(sStreet + "," & "+")
        End If
        If txtclient_city.Text <> "" Then
            sCity = txtclient_city.Text.Replace("  ", "+")
            queryaddress.Append(sCity + "," & "+")
        End If
        If ttxtclient_city.Text <> "" Then
            sPincode = ttxtclient_city.Text.Replace("  ", "+")
            queryaddress.Append(sPincode)
        End If
        If txtclient_state.Text <> "" Then
            sState = txtclient_state.Text.Replace("  ", "+")
            queryaddress.Append(sState + "," & "+")
        End If

        WBR.Navigate(queryaddress.ToString())

回答by Johan Stenstr?m

The Google Maps Control 2017 project wraps Google Maps API as ASP.NET Custom Control, providing an easy and fast way of adding Google Maps in your ASP.NET C# or VB pages with "Zero-Written-JavaScript" code.

Google Maps Control 2017 项目将 Google Maps API 包装为 ASP.NET 自定义控件,提供了一种使用“零编写 JavaScript”代码在 ASP.NET C# 或 VB 页面中添加 Google 地图的简单快捷的方法。

ASP.NET Google Maps Control includes many features (markers, polyline, polygons, directions) and gives you almost all Google Maps API functionality in enjoyable ASP.NET way of coding.

ASP.NET Google Maps Control 包括许多功能(标记、折线、多边形、方向),并以愉快的 ASP.NET 编码方式为您提供几乎所有 Google Maps API 功能。

PM>Install-Package GoogleMapControl

PM>Install-Package GoogleMapControl