locked
Virtual Earth and C# Desktop applications RRS feed

  • Question

  • Greetings fellow developers,

    Is there anyone out there who has successfully integrated Virtual Earth into a standalone desktop application?
    All of the samples I have found create custom controls which embed a web browser and a custom HTML file and then launch the HTML file when the embedded browser loads.

    All of the samples are quck throw togethers and I am hoping that someone out there has a more comprehensive sample which they would be willing to share: )

    Thanks in advance,
    Robert Lancaster

    Monday, June 2, 2008 11:23 AM

Answers

  • Instead of creating a seperate HTML file you can dynamically generate the markup and write it to the WebBrowser object through the DocumentText or Document Stream Properties.

     

    The sample below is a quick throw together but I hope will be helpful. The sample displays a form with a couple of text boxes at the top for the latitude and longitude and a button to plot the point described by the provided latitude and longitude.  When the control opens the map is displayed centerd roughly on Seattle. The javascript gets this location from the c# code through the window.external attribute .  If you plot a point, the map will center on that point and display the pushpin.  This is accomplished using the WebBrowser.Document.InvokeScript method.  The map resize behavior is accomplished the same way. (In design mode I anchored the WebBrowser, webBrowser1, to the top, bottom and both sides so that when the main form resizes webBrowser1 resizes with it.

     

     

    Form1.cs

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.Web;

    namespace WindowsApplication1

    {

    public partial class Form1 : Form

    {

    public Form1()

    {

    InitializeComponent();

    Location loc = new Location();

    loc.Latitude = 47.6;

    loc.Longitude = -122.33;

    webBrowser1.ObjectForScripting = loc;

    StringBuilder markUp = new StringBuilder();

    markUp.Append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd/\">");

    markUp.Append("<html>\n");

    markUp.Append("<head>\n");

    markUp.Append("<title></title>\n");

    markUp.Append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");

    markUp.Append("<script type=\"text/javascript\" src=\"http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1\"></script>\n");

    markUp.Append("<script type=\"text/javascript\">\n");

     

    //Script to create the map and display it

    markUp.Append("var map = null;\n");

    markUp.Append("pinid=0; function GetMap(){latLong=null; map = new VEMap('myMap'); if(window.external != null){latLong = new VELatLong(window.external.Latitude,window.external.Longitude);} map.LoadMap(latLong); }\n");

     

    //Script to Add Pushpins

    markUp.Append("function AddPushpin(lat,lon)\n{map.SetCenter(new VELatLong(lat,lon));\n\tvar shape = new VEShape(VEShapeType.Pushpin, new VELatLong(lat,lon));\n\tshape.SetTitle('test');\n\tshape.SetDescription('This is shape number '+ pinid);\n\tpinid++;\n\tmap.AddShape(shape);\n}");

     

    //Script To Resize map

    markUp.Append("function ResizeMap(w,h)\n{\n\tmap.Resize(w, h);\n\tmyMap.style.width = w + \"px\";\n\tmyMap.style.height = h + \"px\";\n}");

    markUp.Append("</script>\n");

     

    markUp.Append("<body onload=\"GetMap();\">");

    markUp.AppendFormat("<div id='myMap' style=\"position:relative; width:{0}px; height:{1}px;\"></div>\n", webBrowser1.Width, webBrowser1.Height);

    markUp.Append("</body>\n");

    markUp.Append("</html>\n");

    webBrowser1.DocumentText = markUp.ToString();

    }

    private void PlotButton_Click(object sender, EventArgs e)

    {

    webBrowser1.Document.InvokeScript("AddPushpin",new object[]{LatitudeTextBox.Text, LongitudeTextBox.Text});

    }

    private void webBrowser1_Resize(object sender, EventArgs e)

    {

    webBrowser1.Document.InvokeScript("ResizeMap", new object[] { webBrowser1.Width, webBrowser1.Height });

    }

    }

    }

     

     

    Location.cs

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Runtime.InteropServices;

    namespace WindowsApplication1

    {

    [ComVisible(true)]

    public class Location

    {

    private double latitude = 0;

    private double longitude = 0;

    public double Latitude

    {

    get { return latitude; }

    set { latitude = value; }

    }

    public double Longitude

    {

    get { return longitude; }

    set { longitude = value; }

    }

    }

    }

     

     

    *Note: this sample has Zero error handling or type checking for user input into the text boxes.

    Thursday, June 5, 2008 6:27 PM

All replies

  • That's the way to go. Add a webbrowser control on your form and load your virtual earth HTML page.

     

    Then make your form class COM visible like this:

     

    Code Snippet

    [ComVisible(true)]

    public partial class frmTest : Form

    {

     

      ...

      public void mapZoomChanged(int level)

      {

        // Called from javascript on onendzoom event

        ...

      }

    }

     

     

    Then you are able to call functions of your form class from javascript inside your HTML page. Like this:

     

    Code Snippet

    map = new VEMap('myMap');

    map.onLoadMap = function()

    {

      map.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);

      map.AttachEvent('onendzoom', mapZoomChanged);

      ...

    }

     

    ...

     

    function mapZoomChanged(e)

    {

      window.external.mapZoomChanged(e.zoomLevel);

    }

     

    Maarten
    Thursday, June 5, 2008 7:52 AM
  • Instead of creating a seperate HTML file you can dynamically generate the markup and write it to the WebBrowser object through the DocumentText or Document Stream Properties.

     

    The sample below is a quick throw together but I hope will be helpful. The sample displays a form with a couple of text boxes at the top for the latitude and longitude and a button to plot the point described by the provided latitude and longitude.  When the control opens the map is displayed centerd roughly on Seattle. The javascript gets this location from the c# code through the window.external attribute .  If you plot a point, the map will center on that point and display the pushpin.  This is accomplished using the WebBrowser.Document.InvokeScript method.  The map resize behavior is accomplished the same way. (In design mode I anchored the WebBrowser, webBrowser1, to the top, bottom and both sides so that when the main form resizes webBrowser1 resizes with it.

     

     

    Form1.cs

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Text;

    using System.Windows.Forms;

    using System.Web;

    namespace WindowsApplication1

    {

    public partial class Form1 : Form

    {

    public Form1()

    {

    InitializeComponent();

    Location loc = new Location();

    loc.Latitude = 47.6;

    loc.Longitude = -122.33;

    webBrowser1.ObjectForScripting = loc;

    StringBuilder markUp = new StringBuilder();

    markUp.Append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd/\">");

    markUp.Append("<html>\n");

    markUp.Append("<head>\n");

    markUp.Append("<title></title>\n");

    markUp.Append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n");

    markUp.Append("<script type=\"text/javascript\" src=\"http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.1\"></script>\n");

    markUp.Append("<script type=\"text/javascript\">\n");

     

    //Script to create the map and display it

    markUp.Append("var map = null;\n");

    markUp.Append("pinid=0; function GetMap(){latLong=null; map = new VEMap('myMap'); if(window.external != null){latLong = new VELatLong(window.external.Latitude,window.external.Longitude);} map.LoadMap(latLong); }\n");

     

    //Script to Add Pushpins

    markUp.Append("function AddPushpin(lat,lon)\n{map.SetCenter(new VELatLong(lat,lon));\n\tvar shape = new VEShape(VEShapeType.Pushpin, new VELatLong(lat,lon));\n\tshape.SetTitle('test');\n\tshape.SetDescription('This is shape number '+ pinid);\n\tpinid++;\n\tmap.AddShape(shape);\n}");

     

    //Script To Resize map

    markUp.Append("function ResizeMap(w,h)\n{\n\tmap.Resize(w, h);\n\tmyMap.style.width = w + \"px\";\n\tmyMap.style.height = h + \"px\";\n}");

    markUp.Append("</script>\n");

     

    markUp.Append("<body onload=\"GetMap();\">");

    markUp.AppendFormat("<div id='myMap' style=\"position:relative; width:{0}px; height:{1}px;\"></div>\n", webBrowser1.Width, webBrowser1.Height);

    markUp.Append("</body>\n");

    markUp.Append("</html>\n");

    webBrowser1.DocumentText = markUp.ToString();

    }

    private void PlotButton_Click(object sender, EventArgs e)

    {

    webBrowser1.Document.InvokeScript("AddPushpin",new object[]{LatitudeTextBox.Text, LongitudeTextBox.Text});

    }

    private void webBrowser1_Resize(object sender, EventArgs e)

    {

    webBrowser1.Document.InvokeScript("ResizeMap", new object[] { webBrowser1.Width, webBrowser1.Height });

    }

    }

    }

     

     

    Location.cs

    using System;

    using System.Collections.Generic;

    using System.Text;

    using System.Runtime.InteropServices;

    namespace WindowsApplication1

    {

    [ComVisible(true)]

    public class Location

    {

    private double latitude = 0;

    private double longitude = 0;

    public double Latitude

    {

    get { return latitude; }

    set { latitude = value; }

    }

    public double Longitude

    {

    get { return longitude; }

    set { longitude = value; }

    }

    }

    }

     

     

    *Note: this sample has Zero error handling or type checking for user input into the text boxes.

    Thursday, June 5, 2008 6:27 PM
  • Thank you much - excellent example - exactly what I was looking for - thanks for posting

    Friday, July 18, 2008 10:27 PM
  • There is a new asp.net control that has recently been published by the live team:

     

    http://dev.live.com/blogs/devlive/archive/2008/07/27/386.aspx

     

    Cheers

     

    Wednesday, August 6, 2008 7:47 AM
  •  

    there's a winforms control you can user as a starter @ codeplex: http://www.codeplex.com/VEarthControl
    Thursday, August 7, 2008 8:01 AM
  • Thanks a tonnnn !!! veryyy helpful
    Friday, May 1, 2009 2:36 PM
  • This solution that uses a WebBrowser control is not the best way to use VE in WPF or WinForm application.
    In fact, the WebBrowser control is rendered in front of everything you set... you can't add a simple button in front of the WebBrowser element in your application (especially in WPF).

    Adding to the fact that for some specific development, you might have some problems to fire the correct events.

    One another good way to use VE inside your application is on codeplex too right here: http://virtualearthwpf.codeplex.com/
    I'm working on a full WPF control, but for the moment I don't have the time to continue it. I will publish it directly on Codeplex as soon as possible and when it will be somehow worth something.
    My blog (FR): http://blogs.developpeur.org/nicoboo/ Twitter: http://twitter.com/nicolasboonaert/
    Friday, May 8, 2009 5:54 PM
  • Depending on your needs, I would take a hard look at the VE Web Services.  We implemented a WinForm app that used the Mappoint Web Services succesfully. 

    The concept is basically that you get a bitmap from the web service that you can use in what ever form you want.  We used it as a backdrop and then overlayed our business objects on top.  You have to do the math to coorelate between a pixel and a lat long and vice versa, but it gives you the most flexability.

    Another option is to use the VE 3D control.  It is usable in a WinForm app and has an object model to control it.  Take a look at the VE 3d Team blog for more info  http://blogs.msdn.com/VirtualEarth3D/  They discuss in a post about how to integrate it with winforms.

    There is a project on codeplex that uses this control in a wpf app.  Again, see the above blog for details.

    There are commercial products that provide the features you want also.  Take a look at www.mapdotnet.com

    Or you could build your own tile client.  <grin>

    If you are going the silverlight route, there are obviously several options discussed already.

    Tuesday, May 12, 2009 12:06 PM