我想在VB 2010中编写一个Windows窗体应用程序,允许用户在Google地图上搜索和查看地址或坐标点。我已经通过使用WebBrowser项完成了这项工作。但是我想使用包装器,这样我就可以向用户显示地图,但仍然可以移动和缩放地图或给出指示等。我知道在开发ASP.NET网站时有办法做到这一点,但我想为WindowsForms应用程序执行此操作。有人可以帮忙吗?
答案 0 :(得分:6)
可能为时已晚,但我最近不得不在vb中处理谷歌地图并希望分享我的解决方案:
本示例的第一部分介绍了如何实现它。在第二部分,我将解释它是如何工作的。这试图成为一个普遍的例子。地图的模板(参见步骤3)和示例函数是完全可自定义的。
################################# IMPLEMENTATION ########## ################## 强>
步骤1。首先,创建一个新项目并选择Windows Form Application。我们将其名称保留为“Form1”。
第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;写的 项目名称
第6步。添加新课程(右键点击您的项目&gt; add-&gt;类)。在我的示例中,我将其称为GoogleMapHelper。
第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文件放在那里。 就我而言:
我在Form1中创建了两个按钮来说明地图与WF的交互方式。以下是它的外观:
以下是代码:
<强> 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上遇到了一些许可问题。
答案 2 :(得分:0)
Google Maps API for .NET似乎是您正在寻找的
来自网站
此项目旨在提供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