[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Visual Studio 2013 - Get latitude Longitude from google Map in windows project

Posted on 2014-08-16
18
Medium Priority
?
2,963 Views
Last Modified: 2014-09-29
Hi

I'm starting to convert my old VB6 app into Visual studio 2013 for windows desktop application.

I'm still very new to Visual Studio and with the coding structure.

I have a form with a WebBrowser1 that show Google Map. The map can be in Satelitte view or the standard Google Map.

When the form open, it run below code:
Public Class Web_map
    Public StartingAddress As String
    Dim mbDontNavigateNow As Boolean
    Dim OkURLs As String


    Private Sub Web_map_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        StartingAddress = "http://www.8051projects.info/maps.asp?lat=" & latutude_1.Text & "&lon=" & longitude_1.Text
        WebBrowser1.Navigate(StartingAddress)

    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        StartingAddress = "http://www.8051projects.info/maps.asp?lat=" & latutude_1.Text & "&lon=" & longitude_1.Text
        WebBrowser1.Navigate(StartingAddress)
    End Sub
End Class

Open in new window


Now, i would like to add a new feature but i just cant figure this one out.

I saw multiple web link that talk about C# and JavaqScript but i really dont know if this can be done in my app.

What i would like to do is to be able to selevt a specific point on the Map, and it would give me the Latitude and Longitude from it.

Then, it would write the Latitude value in to the Textbox1 and the Longitude into the Textbox2.

How can i do that? Can i merge other code in my app to make this happen?

Thanks again for your help
0
Comment
Question by:Wilder1626
  • 8
  • 8
  • 2
18 Comments
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 40294028
You will need some javascript to get the coordinates of the click, and then you will need even more javascript to send a message to your desktop application. It is not a trivial task. Good tutorial here (C#):
http://www.codeproject.com/Articles/36517/Communicating-from-the-Browser-to-a-Desktop-Applic
0
 
LVL 55

Expert Comment

by:Jaime Olivares
ID: 40294030
For getting the coordinates of a click event in javascript you will need:

google.maps.event.addListener(map, 'click', function(event) 
{
    var latitude = event.latLng.lat();
    var longitude = event.latLng.lng();
    // send the latitude and longitude values to the desktop application here
});

Open in new window

0
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 2000 total points
ID: 40294233
Jaime, your general idea is correct but that link talks about communicating between 2 separate processes whereas this question is about a webbrowser component contained in a winforms application. Also, the click event doesn't work with the code in the referred page, seems to be for a newer version of GMap.

I took some inspiration from an old solution here: http://www.experts-exchange.com/Programming/Languages/.NET/Q_23582209.html#a22311886 and came up with this:
Public Class Form1

    Public StartingAddress As String
    Dim mbDontNavigateNow As Boolean
    Dim OkURLs As String

    Dim base_url As String = "http://www.8051projects.info/maps.asp"

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        StartingAddress = base_url & "?lat=" & latutude_1.Text & "&lon=" & longitude_1.Text
        WebBrowser1.Navigate(StartingAddress)
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        StartingAddress = base_url & "?lat=" & latutude_1.Text & "&lon=" & longitude_1.Text
        WebBrowser1.Navigate(StartingAddress)
    End Sub

    ' code copied from accepted solution here: http://www.experts-exchange.com/Programming/Languages/.NET/Q_23582209.html#a22311886

    Private WithEvents _document As HtmlDocument

    Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
        _document = Me.WebBrowser1.Document
    End Sub

    Private Sub _document_Click(ByVal sender As Object, ByVal e As System.Windows.Forms.HtmlElementEventArgs) Handles _document.Click
        Try
            ' to use mshtml don't forget to add a reference to the Microsoft.mshtml dll (via menu Project|Add Reference)
            Dim lat1 As mshtml.HTMLInputElement = _document.All("lat1").DomElement
            Dim lon1 As mshtml.HTMLInputElement = _document.All("lon1").DomElement
            Dim lat As String = lat1.value
            Dim lon As String = lon1.value

            If String.IsNullOrEmpty(lat) Or String.IsNullOrEmpty(lon) Then
                'Label1.Text = "clicked outside map? got nothing :-("
            Else
                'Label1.Text = String.Format("clicked @ ({0}, {1})", lat, lon)
                lat1.value = ""
                lon1.value = ""
            End If
        Catch ex As Exception
            'MsgBox("error while handling browser click: " & ex.ToString, , ex.Message)
        End Try
    End Sub

End Class

Open in new window

For testing I changed the base_url to "http://schutt.nl/ee/Q_28499086/", where I've put an index.html containing the generated source from the original website.

I commented out the lines that show the click, you can handle the information any way you want, maybe you also want to start out just showing it in a label, then just add that to your form and take away the comment quotes.

By the way I started out using a more complicated function to check for data from the page because I suspected the click functions could be called in a random order but after testing I'm satisfied that the map click is always called before the document click which should be logical from an event bubbling perspective. I did leave in the code to clear the hidden elements after reading them just to make sure you never use old values again. This is mainly important when you click on (or near) control elements like the zoom bar or map type selection buttons (because the document click will be called in that case but no map click).

In the page itself I added a number of things. The QueryString function is just for me to use the lat/lon parameters. The hidden input elements (line 7 in the code below) and the javascript click function (lines 68-71 in the code below) are needed so I do hope you have access to the source of that page otherwise a more complex solution will be needed (something like reading the map bounds and calculate the position within that).
  <body onunload="GUnload()">
<table>
    <div id="map" style="width: 800px; height: 600px"></div>
</table>

<!-- ADDED: hidden input elements -->
<input type="hidden" id="lat1"><input type="hidden" id="lon1">

    <noscript><b>JavaScript must be enabled in order for you to use Google Maps.</b> 
      However, it seems JavaScript is either disabled or not supported by your browser. 
      To view Google Maps, enable JavaScript by changing your browser options, and then 
      try again.
    </noscript>
 
    <script type="text/javascript">
    //<![CDATA[

   // ADDED: (TEMP) use querystring in javascript
   var QueryString = function () {
      var query_string = {};
      var query = window.location.search.substring(1);
      var vars = query.split("&");
      for (var i=0;i<vars.length;i++) {
      var pair = vars[i].split("=");
      // If first entry with this name
      if (typeof query_string[pair[0]] === "undefined") {
      query_string[pair[0]] = pair[1];
      // If second entry with this name
      } else if (typeof query_string[pair[0]] === "string") {
      var arr = [ query_string[pair[0]], pair[1] ];
      query_string[pair[0]] = arr;
      // If third or later entry with this name
      } else {
      query_string[pair[0]].push(pair[1]);
      }
      } 
      return query_string;
   } ();
   var parLat = QueryString.lat || 51.939581;
   var parLon = QueryString.lon || 4.597851;

 	//Convert degminsec to decimal degrees
	
    if (GBrowserIsCompatible()) { 

      // A function to create the marker and set up the event window
      // Dont try to unroll this function. It has to be here for the function closure
      // Each instance of the function preserves the contends of a different instance
      // of the "marker" and "html" variables which will be needed later when the event triggers.    
      function createMarker(point,html) {
        var marker = new GMarker(point);
        GEvent.addListener(marker, "click", function() {
          marker.openInfoWindowHtml(html);
        });
        return marker;
      }

      // Display the map, with some controls and set the initial location 
      var map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      var point = new GLatLng(parLat,parLon);
      map.setCenter(point,13);
      var marker = createMarker(point,'Welcome to 8051projects.info')
      map.addOverlay(marker);

      // ADDED: event handler to fill hidden input elements
      google.maps.event.addListener(map, 'click', function(ovl, latLng) {
          document.getElementById('lat1').value = latLng.lat();
          document.getElementById('lon1').value = latLng.lng();
      });

    }
    
    // display a warning if the browser was not compatible
    else {
      alert("Sorry, the Google Maps API is not compatible with this browser");
    }

    // This Javascript is based on code provided by the
    // Blackpool Community Church Javascript Team
    // http://www.commchurch.freeserve.co.uk/   
    // http://econym.googlepages.com/index.htm

    //]]>
    </script>
  </body>

Open in new window

0
NFR key for Veeam Agent for Linux

Veeam is happy to provide a free NFR license for one year.  It allows for the non‑production use and valid for five workstations and two servers. Veeam Agent for Linux is a simple backup tool for your Linux installations, both on‑premises and in the public cloud.

 
LVL 11

Author Comment

by:Wilder1626
ID: 40294557
Hi Jaime and Robert,

Thanks a lot for all the ideas. Let me test this and i will come back shortly.
0
 
LVL 11

Author Comment

by:Wilder1626
ID: 40294892
Hi Robert

After doing some test, it looks like i cant get the lat and long when clickling on the map. I beleive that this is the code that should give it to me. Correct?

Private Sub _document_Click(ByVal sender As Object, ByVal e As System.Windows.Forms.HtmlElementEventArgs) Handles _document.Click
        Try
            ' to use mshtml don't forget to add a reference to the Microsoft.mshtml dll (via menu Project|Add Reference)
            Dim lat1 As mshtml.HTMLInputElement = _document.All("lat1").DomElement
            Dim lon1 As mshtml.HTMLInputElement = _document.All("lon1").DomElement
            Dim lat As String = lat1.text
            Dim lon As String = lon1.value

            If String.IsNullOrEmpty(lat) Or String.IsNullOrEmpty(lon) Then
                ' Label1.Text = "clicked outside map? got nothing :-("
            Else
                ' Label1.Text = String.Format("clicked @ ({0}, {1})", lat, lon)
                lat1.value = ""
                lon1.value = ""
            End If
        Catch ex As Exception
            ' MsgBox("error while handling browser click: " & ex.ToString, , ex.Message)
        End Try
    End Sub

Open in new window

0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40294898
yes but it will only work if the page is filling the hidden input elements.

EDIT: and check the commented out lines, maybe use a breakpoint?
0
 
LVL 11

Author Comment

by:Wilder1626
ID: 40294916
i see. Thanks

I was using the web link from someone else project. Project i found on the web.

I may need to go for another web option then. opne that does have the hidden input elements.

Let me take a look at this.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40294923
Ok, in the meantime you could use the page on my website? Otherwise like I said I think you need to get the bounds from the google objects but if the page is not yours then this would be asking for problems in the future as they might change the page and stop your program from working so better use a page that's under your own control.
0
 
LVL 11

Author Comment

by:Wilder1626
ID: 40294982
This is great, a huge thanks. I will gladly use your page until i start creating mind.

I did a small update like this:
        Try
            ' to use mshtml don't forget to add a reference to the Microsoft.mshtml dll (via menu Project|Add Reference)
            Dim lat1 As mshtml.HTMLInputElement = _document.All("lat1").DomElement
            Dim lon1 As mshtml.HTMLInputElement = _document.All("lon1").DomElement
            Dim lat As String = lat1.value
            Dim lon As String = lon1.value

            If String.IsNullOrEmpty(lat) Or String.IsNullOrEmpty(lon) Then
                ' Label1.Text = "clicked outside map? got nothing :-("
            Else
                Label1.Text = String.Format("({0}, {1})", lat, lon)
                lat1.value = ""
                lon1.value = ""
                latitude_2.Text = String.Format("{0}", lat)
                longitude_2.Text = String.Format("{0}", lon)


            End If
        Catch ex As Exception
            MsgBox("error while handling browser click: " & ex.ToString, , ex.Message)
        End Try

Open in new window


Is there a way to format the lat and long to be "0.00000""
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40294986
Here's a version that works with the original page, by getting the bounds of the map:
    Private Sub _document_Click(ByVal sender As Object, ByVal e As System.Windows.Forms.HtmlElementEventArgs) Handles _document.Click
        Try
            Dim cmp As Point = e.ClientMousePosition
            Dim map As Rectangle = WebBrowser1.Document.All("map").OffsetRectangle
            Dim x As Double = cmp.X - map.X
            Dim y As Double = cmp.Y - map.Y
            If x >= 0 And x < map.Width And y >= 0 And y < map.Height Then
                Dim jsval As String = WebBrowser1.Document.InvokeScript("eval", {"map.getBounds().Ca.j+';'+map.getBounds().Ca.k+';'+map.getBounds().pa.j+';'+map.getBounds().pa.k"}).ToString
                Dim mapbounds() As String = jsval.Split(";")
                Dim topleft As New PointF(mapbounds(2), mapbounds(0))
                Dim bottomright As New PointF(mapbounds(3), mapbounds(1))
                Dim lat As Double = topleft.Y + (bottomright.Y - topleft.Y) * y / map.Height
                Dim lon As Double = topleft.X + (bottomright.X - topleft.X) * x / map.Width
                Label1.Text = String.Format("clicked @ ({0}, {1}) jsval={2}", lat, lon, jsval)
            End If
        Catch ex As Exception
            MsgBox("error while handling browser click: " & ex.ToString, , ex.Message)
        End Try
    End Sub

Open in new window

0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40294989
for formatting try:
latitude_2.Text = String.Format("{0:0.00000}", lat)
longitude_2.Text = String.Format("{0:0.00000}", lon)

Open in new window

0
 
LVL 11

Author Comment

by:Wilder1626
ID: 40295014
I see that it still give me the long value, even with :

latitude_2.Text = String.Format("{0:0.00000}", lat)
longitude_2.Text = String.Format("{0:0.00000}", lon)

Open in new window


I just tried the code on your post: ID: 40294986 and i have an error on row 11.
 Dim topleft As New PointF(mapbounds(2), mapbounds(0))

Open in new window


Let me try to figure it out. Ill be back shortly.

Thanks again for your help.
0
 
LVL 11

Author Comment

by:Wilder1626
ID: 40295019
Looks like System.InvalidCastException error while converting the string of the longitude: "-73.6921745578136"

Type SINGLE does not look like something valid.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40295184
At the moment it's not clear to me which version of the code you're using (with or without the javascript changes, also possible other changes), please post some more code in context as well as the exact error. The Single data type should be able to handle numbers like that, but maybe it's about the conversion into a PointF which is not strictly needed.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40295202
For the formatting something strange is happening, you can try it like this:
latitude_2.Text = Math.Round(Convert.ToSingle(lat), 5)
longitude_2.Text = Math.Round(Convert.ToSingle(lon), 5)

Open in new window

For the error on mapbounds, can you put a breakpoint in the code and see what's in the jsval string?
0
 
LVL 11

Author Closing Comment

by:Wilder1626
ID: 40295605
Thanks you so much for your help. Really appriciated

Now, i just need to create the exact same thing that you have on your web page: "http://schutt.nl/ee/Q_28499086/"

If i can replicate it,, this will be more than perfect to me.
0
 
LVL 35

Expert Comment

by:Robert Schutt
ID: 40295656
Ok, great!

However, I don't really understand your last comment, because you do have 2 options:
1) use the first solution I posted, in that case you do need the edited page (with the hidden inputs and click function). But I showed the steps to replicate it and actually you could just copy the page from my website as there is no server side processing in it, just a simple html page.
2) use the solution with the getbounds() (posted in http:/#40294986 ), which works with the original page.
0
 
LVL 11

Author Comment

by:Wilder1626
ID: 40295673
Actually, i was able to replicate it by using your source code below. Now, just need to use FPT to transfer that on the web.

Working on it now, see if it will work.

I will let you know.

Thanks again. i'm learning a lot.


<SCRIPT LANGUAGE="JavaScript">
<!-- Begin
var xy = navigator.appVersion;
xz = xy.substring(0,4);
document.cookie = "ScreenWidth=" + screen.width
document.cookie = "ScreenHeight=" + screen.height
// End -->
</script>


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
    <title>Google Maps</title>
    <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAAdljgOdiavR1ybAqJem3DPxRUtU-YbzJ1ObE5mZjLnE9GJXXfmhRXLHpG2E6aPHTXkF2MEpty1kZpJw" type="text/javascript"></script>
  </head>
  <body onunload="GUnload()">
<table>
    <div id="map" style="width: 800px; height: 600px"></div>
</table>

<!-- ADDED: hidden input elements -->
<input type="hidden" id="lat1"><input type="hidden" id="lon1">

    <noscript><b>JavaScript must be enabled in order for you to use Google Maps.</b> 
      However, it seems JavaScript is either disabled or not supported by your browser. 
      To view Google Maps, enable JavaScript by changing your browser options, and then 
      try again.
    </noscript>
 
    <script type="text/javascript">
    //<![CDATA[

   // ADDED: (TEMP) use querystring in javascript
   var QueryString = function () {
      var query_string = {};
      var query = window.location.search.substring(1);
      var vars = query.split("&");
      for (var i=0;i<vars.length;i++) {
      var pair = vars[i].split("=");
      // If first entry with this name
      if (typeof query_string[pair[0]] === "undefined") {
      query_string[pair[0]] = pair[1];
      // If second entry with this name
      } else if (typeof query_string[pair[0]] === "string") {
      var arr = [ query_string[pair[0]], pair[1] ];
      query_string[pair[0]] = arr;
      // If third or later entry with this name
      } else {
      query_string[pair[0]].push(pair[1]);
      }
      } 
      return query_string;
   } ();

   var parLat = QueryString.lat || 51.939581;
   var parLon = QueryString.lon || 4.597851;

 	//Convert degminsec to decimal degrees
	
    if (GBrowserIsCompatible()) { 

      // A function to create the marker and set up the event window
      // Dont try to unroll this function. It has to be here for the function closure
      // Each instance of the function preserves the contends of a different instance
      // of the "marker" and "html" variables which will be needed later when the event triggers.    
      function createMarker(point,html) {
        var marker = new GMarker(point);
        GEvent.addListener(marker, "click", function() {
          marker.openInfoWindowHtml(html);
        });
        return marker;
      }

      // Display the map, with some controls and set the initial location 
      var map = new GMap2(document.getElementById("map"));
      map.addControl(new GLargeMapControl());
      map.addControl(new GMapTypeControl());
      var point = new GLatLng(parLat,parLon);
      map.setCenter(point,13);
      var marker = createMarker(point,'Welcome to 8051projects.info')
      map.addOverlay(marker);

      // ADDED: event handler to fill hidden input elements
      google.maps.event.addListener(map, 'click', function(ovl, latLng) {
          document.getElementById('lat1').value = latLng.lat();
          document.getElementById('lon1').value = latLng.lng();
      });

    }
    
    // display a warning if the browser was not compatible
    else {
      alert("Sorry, the Google Maps API is not compatible with this browser");
    }

    // This Javascript is based on code provided by the
    // Blackpool Community Church Javascript Team
    // http://www.commchurch.freeserve.co.uk/   
    // http://econym.googlepages.com/index.htm

    //]]>
    </script>
  </body>

</html>

Open in new window

0

Featured Post

Get quick recovery of individual SharePoint items

Free tool – Veeam Explorer for Microsoft SharePoint, enables fast, easy restores of SharePoint sites, documents, libraries and lists — all with no agents to manage and no additional licenses to buy.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface This is the third article about the EE Collaborative Login Project. A Better Website Login System (http://www.experts-exchange.com/A_2902.html) introduces the Login System and shows how to implement a login page. The EE Collaborative Logi…
Have you tried to learn about Unicode, UTF-8, and multibyte text encoding and all the articles are just too "academic" or too technical? This article aims to make the whole topic easy for just about anyone to understand.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
Use Wufoo, an online form creation tool, to make powerful forms. Learn how to choose which pages of your form are visible to your users based on their inputs. The page rules feature provides you with an opportunity to create if:then statements for y…
Suggested Courses

834 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question