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

时间:2012-02-26 09:27:13

标签: vb.net winforms google-maps

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

5 个答案:

答案 0 :(得分:6)

可能为时已晚,但我最近不得不在vb中处理谷歌地图并希望分享我的解决方案:

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

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

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

enter image description here

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

第3步。使用您喜欢的文本编辑器创建名为“googlemap_template.html”的.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>

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

第4步。将googlemap_template.hmtl文件添加到您的项目中(右键点击您的项目 - &gt; add-&gt;现有项目)

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

enter image description here

第6步。添加新课程(右键点击您的项目&gt; add-&gt;类)。在我的示例中,我将其称为GoogleMapHelper。

enter image description here

第7步。将以下代码粘贴到您的课程中:

<强> GoogleMapHelper.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

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

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

enter image description here

我在Form1中创建了两个按钮来说明地图与WF的交互方式。以下是它的外观:

enter image description here

以下是代码:

<强> Form1.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

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

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

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

另外请不要忘记Form1加载函数:

Me.wbmap.ObjectForScripting = Me

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

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

#################################如何工作######## #########################

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

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

答案 1 :(得分:2)

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

GreatMaps on codeplex

答案 2 :(得分:0)

Google Maps API for .NET似乎是您正在寻找的

http://gmaps.codeplex.com/

来自网站

  

此项目旨在提供Google Maps API中提供的所有功能。   它是在C#for .NET Framework 3.5中开发的。

虽然项目是在C#中,但您可以添加对项目的引用,并像使用任何其他引用一样使用它,并在任何符合CLR的语言(包括VB)中编写代码。

答案 3 :(得分:0)

尝试使用此代码获取两个位置之间的方向

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())

答案 4 :(得分:0)

Google Maps Control 2017项目将Google Maps API包装为ASP.NET自定义控件,提供了一种在ASP.NET C#或VB页面中使用&#34; Zero-Written-JavaScript&#添加Google地图的简便快捷方式34;码。

ASP.NET Google地图控件包含许多功能(标记,折线,多边形,方向),并以令人愉快的ASP.NET编码方式为您提供几乎所有Google Maps API功能。

PM&gt;安装包GoogleMapControl