Answered by:
Virtual Earth and C# Desktop applications

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 LancasterMonday, 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.csusing
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{
{
{
InitializeComponent();
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.csusing
System;using
System.Collections.Generic;using
System.Text;using
System.Runtime.InteropServices;namespace
WindowsApplication1{
[
{
{
}
public double Longitude{
}
}
}
*Note: this sample has Zero error handling or type checking for user input into the text boxes.
- Proposed as answer by Batul Saifee Friday, May 1, 2009 2:35 PM
- Marked as answer by Ricky_BrundrittModerator Friday, November 20, 2009 6:42 PM
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 Snippetmap = new VEMap('myMap');
map.onLoadMap = function()
{
map.SetScaleBarDistanceUnit(VEDistanceUnit.Kilometers);
map.AttachEvent('onendzoom', mapZoomChanged);
...
}
...
function mapZoomChanged(e)
{
window.external.mapZoomChanged(e.zoomLevel);
}
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.csusing
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{
{
{
InitializeComponent();
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.csusing
System;using
System.Collections.Generic;using
System.Text;using
System.Runtime.InteropServices;namespace
WindowsApplication1{
[
{
{
}
public double Longitude{
}
}
}
*Note: this sample has Zero error handling or type checking for user input into the text boxes.
- Proposed as answer by Batul Saifee Friday, May 1, 2009 2:35 PM
- Marked as answer by Ricky_BrundrittModerator Friday, November 20, 2009 6:42 PM
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 -
Thursday, August 7, 2008 8:01 AM
-
Thanks a tonnnn !!! veryyy helpfulFriday, 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