Click here to Skip to main content
15,891,688 members
Articles / Desktop Programming / Windows Forms

GMap.NET - Great Maps for Windows Forms and Presentation

Rate me:
Please Sign up or sign in to vote.
4.80/5 (135 votes)
16 Apr 2013MIT1 min read 1.8M   611   508   373
GMap.NET is a powerful, free, cross platform, Open Source .NET control. It enables the use of routing, geocoding, and maps from Google, Yahoo!, OpenStreet in Windows Forms and Presentation, and supports caching!

GMapNET/GMapNETv7cp.PNG

Introduction

Google Maps are cool, yeah? But it's useful only in the browser, and is insufficient for real time tracking. It also does not have cache so Google servers are overloaded. This control removes all these deficiencies! It also gives the .NET developer unlimited ability to extend it!

GMap.NET is great and Powerful, Free, cross platform, open source .NET control. Enable use routing, geocoding, directions and maps from Google, Yahoo!, Bing, OpenStreetMap, ArcGIS, Pergo, SigPac, Yandex, Mapy.cz, Maps.lt, iKarte.lv, NearMap, OviMap, CloudMade, WikiMapia, MapQuest in Windows Forms & Presentation, supports caching and runs on windows mobile! 

Background

The basic idea is simple: get the required data from Google/etc., cache it, and use it. Fast, simple, and practical.

Using the Code

It's more than easy. GMap.NET.dll and GMap.NET.WindowsForms.dll contain the user control. Add it to your project and simply use it.

Here are the basic control initial options: 

C#
public MainForm()
{

InitializeComponent();

try
{
   System.Net.IPHostEntry e =
        System.Net.Dns.GetHostEntry("www.google.com");
}
catch
{
   MainMap.Manager.Mode = AccessMode.CacheOnly;
   MessageBox.Show("No internet connection avaible, going to CacheOnly mode.", 
         "GMap.NET - Demo.WindowsForms", MessageBoxButtons.OK,
         MessageBoxIcon.Warning);
}

// config map
MainMap.MapProvider = GMapProviders.OpenStreetMap;
MainMap.Position = new PointLatLng(54.6961334816182, 25.2985095977783);
MainMap.MinZoom = 0;
MainMap.MaxZoom = 24;
MainMap.Zoom = 9;

// add your custom map db provider
//GMap.NET.CacheProviders.MySQLPureImageCache ch = new GMap.NET.CacheProviders.MySQLPureImageCache();
//ch.ConnectionString = @"server=sql2008;User Id=trolis;Persist Security Info=True;database=gmapnetcache;password=trolis;";
//MainMap.Manager.SecondaryCache = ch;

// set your proxy here if need
//GMapProvider.WebProxy = new WebProxy("10.2.0.100", 8080);
//GMapProvider.WebProxy.Credentials = new NetworkCredential("ogrenci@bilgeadam.com", "bilgeada");

// map events
{
   MainMap.OnPositionChanged += new PositionChanged(MainMap_OnPositionChanged);

   MainMap.OnTileLoadStart += new TileLoadStart(MainMap_OnTileLoadStart);
   MainMap.OnTileLoadComplete += new TileLoadComplete(MainMap_OnTileLoadComplete);

   MainMap.OnMapZoomChanged += new MapZoomChanged(MainMap_OnMapZoomChanged);
   MainMap.OnMapTypeChanged += new MapTypeChanged(MainMap_OnMapTypeChanged);

   MainMap.OnMarkerClick += new MarkerClick(MainMap_OnMarkerClick);
   MainMap.OnMarkerEnter += new MarkerEnter(MainMap_OnMarkerEnter);
   MainMap.OnMarkerLeave += new MarkerLeave(MainMap_OnMarkerLeave);

   MainMap.OnPolygonEnter += new PolygonEnter(MainMap_OnPolygonEnter);
   MainMap.OnPolygonLeave += new PolygonLeave(MainMap_OnPolygonLeave);

   MainMap.OnRouteEnter += new RouteEnter(MainMap_OnRouteEnter);
   MainMap.OnRouteLeave += new RouteLeave(MainMap_OnRouteLeave);

   MainMap.Manager.OnTileCacheComplete += new TileCacheComplete(OnTileCacheComplete);
   MainMap.Manager.OnTileCacheStart += new TileCacheStart(OnTileCacheStart);
   MainMap.Manager.OnTileCacheProgress += new TileCacheProgress(OnTileCacheProgress);
}   
} 

As you can see, the control options are quite simple. And there is nothing more to add.

Points of Interest

Well, it was quite cryptic to figure out how Google manages tiles, what coordinate system it uses, the JSON decryption, etc.

History

Go to the project's CodePlex site to get a running update of any changes or improvements I've made.  

License

This article, along with any associated source code and files, is licensed under The MIT License


Written By
Software Developer
Lithuania Lithuania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralMy vote of 5 Pin
iskandar700727-Jul-10 18:47
iskandar700727-Jul-10 18:47 
QuestionAre you mad? Pin
Jim Buckley Barrett22-Apr-10 6:12
Jim Buckley Barrett22-Apr-10 6:12 
AnswerRe: Are you mad? Pin
radioman.lt22-Apr-10 7:27
radioman.lt22-Apr-10 7:27 
GeneralRe: Are you mad? Pin
Jim Buckley Barrett22-Apr-10 22:10
Jim Buckley Barrett22-Apr-10 22:10 
GeneralRe: Are you mad? Pin
franva3-Jun-10 20:57
franva3-Jun-10 20:57 
GeneralSafety of Core class Pin
Bernhard Hiller1-Apr-10 4:49
Bernhard Hiller1-Apr-10 4:49 
GeneralRe: Safety of Core class Pin
radioman.lt1-Apr-10 5:36
radioman.lt1-Apr-10 5:36 
GeneralRe: Safety of Core class Pin
Bernhard Hiller4-Apr-10 22:31
Bernhard Hiller4-Apr-10 22:31 
In the button click handler of a windows form (on an old single core computer running XP), I read the zoom and position values, set these two values in the Core object
_Core.Zoom = zoom;
_Core.CurrentPosition = new PointLatLng(latitude, longitude);

and then it starts two times to get the tile from Google.
Often the error is then
05.04.2010 10:21:43.9375, Thread=11 Core.UpdateBaunds()
OnTileLoadStart: 1 tiles to load at zoom 14, time: 10:21:43.9375000
05.04.2010 10:21:43 GMapDialog._Core_OnTileLoadStart
05.04.2010 10:21:43.9375, Thread=11 Core.UpdateBaunds is adding task 14 - {X=10326,Y=7695}
05.04.2010 10:21:43 GMapDialog._Core_OnNeedInvalidation
05.04.2010 10:21:43 GMapDialog._Core_OnMapDrag
05.04.2010 10:21:43 GMapDialog._Core_OnMapZoomChanged
05.04.2010 10:21:43 GMapDialog._Core_OnCurrentPositionChanged: point={Lat=10,85, Lng=46,9}
05.04.2010 10:21:43.9375, Thread=11 Core.UpdateBaunds()
OnTileLoadStart: 1 tiles to load at zoom 14, time: 10:21:43.9531250
05.04.2010 10:21:43 GMapDialog._Core_OnTileLoadStart
TileLoadQueue: 0
ProcessLoadTask: 14 - {X=10326,Y=7695}
05.04.2010 10:21:43.9531, Thread=8 Core.ProcessLoadTask  calling GetImageFrom(type=GoogleSatellite, pos={X=10326,Y=7695}, zoom=14
Starting GetResponse: {X=10326,Y=7695}
05.04.2010 10:21:43.9531, Thread=11 Core.UpdateBaunds is adding task 14 - {X=10326,Y=7695}
05.04.2010 10:21:43 GMapDialog._Core_OnNeedInvalidation
05.04.2010 10:21:43 GMapDialog._Core_OnMapDrag
05.04.2010 10:21:43 GMapDialog._Core_OnCurrentPositionChanged: point={Lat=10,85, Lng=46,9}
TileLoadQueue: 0
ProcessLoadTask: 14 - {X=10326,Y=7695}
05.04.2010 10:21:43.9843, Thread=18 Core.ProcessLoadTask  calling GetImageFrom(type=GoogleSatellite, pos={X=10326,Y=7695}, zoom=14
GetResponse OK: {X=10326,Y=7695}
Starting GetResponseStream: {X=10326,Y=7695}
GetResponseStream OK: {X=10326,Y=7695}
EnqueueCacheTask: {X=10326,Y=7695}
A first chance exception of type 'System.IndexOutOfRangeException' occurred in System.dll
GetImageFrom: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.Generic.Queue`1.Enqueue(T item)
   at GMap.NET.GMaps.EnqueueCacheTask(CacheItemQueue task) in D:\Daten\Projects\GMap\GMap.NET\GMaps.cs:line 780
   at GMap.NET.GMaps.GetImageFrom(MapType type, Point pos, Int32 zoom) in D:\Daten\Projects\GMap\GMap.NET\GMaps.cs:line 2193
ProcessLoadTask: 14 - {X=10326,Y=7695} -> empty tile, retry 0
05.04.2010 10:21:44.0937, Thread=8 Core.ProcessLoadTask  calling GetImageFrom(type=GoogleSatellite, pos={X=10326,Y=7695}, zoom=14
OnTileLoadComplete: 160ms, MemoryCacheSize: 0,215575218200684MB
05.04.2010 10:21:44 GMapDialog._Core_OnTileLoadComplete
05.04.2010 10:21:44 GMapDialog._Core_OnNeedInvalidation
Starting GetResponse: {X=10326,Y=7695}
GetResponse OK: {X=10326,Y=7695}
Starting GetResponseStream: {X=10326,Y=7695}
GetResponseStream OK: {X=10326,Y=7695}
EnqueueCacheTask: {X=10326,Y=7695}
A first chance exception of type 'System.IndexOutOfRangeException' occurred in System.dll
GetImageFrom: System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Collections.Generic.Queue`1.Enqueue(T item)
   at GMap.NET.GMaps.EnqueueCacheTask(CacheItemQueue task) in D:\Daten\Projects\GMap\GMap.NET\GMaps.cs:line 780
   at GMap.NET.GMaps.GetImageFrom(MapType type, Point pos, Int32 zoom) in D:\Daten\Projects\GMap\GMap.NET\GMaps.cs:line 2193
ProcessLoadTask: 14 - {X=10326,Y=7695} -> empty tile, retry 0
05.04.2010 10:21:44.2500, Thread=18 Core.ProcessLoadTask  calling GetImageFrom(type=GoogleSatellite, pos={X=10326,Y=7695}, zoom=14
OnTileLoadComplete: 160ms, MemoryCacheSize: 0,215575218200684MB
05.04.2010 10:21:44 GMapDialog._Core_OnTileLoadComplete
05.04.2010 10:21:44 GMapDialog._Core_OnNeedInvalidation
The thread 0xdd8 has exited with code 0 (0x0).
The thread '<No Name>' (0xff4) has exited with code 0 (0x0).

With the additional BeginUpdate() and EndUpdate() functions above, the error does not happen. By the way, the error does not become visible to the user, it is only visible in the debug output. I added some further debug messages including the thread number, so I could find out where the problem was.
In the example above, thread 8 was initiated after changing the zoom, and thread 18 after changing the position, just 30 ms later.
GeneralRe: Safety of Core class [modified] Pin
radioman.lt5-Apr-10 2:01
radioman.lt5-Apr-10 2:01 
GeneralRe: Safety of Core class Pin
Bernhard Hiller9-Apr-10 2:02
Bernhard Hiller9-Apr-10 2:02 
GeneralRe: Safety of Core class Pin
radioman.lt9-Apr-10 2:16
radioman.lt9-Apr-10 2:16 
GeneralLicensing Pin
apollo-house27-Mar-10 0:58
apollo-house27-Mar-10 0:58 
GeneralRe: Licensing Pin
radioman.lt27-Mar-10 2:54
radioman.lt27-Mar-10 2:54 
GeneralRe: Licensing Pin
apollo-house27-Mar-10 3:28
apollo-house27-Mar-10 3:28 
RantThink hard before you use this software Pin
TechnologyIS19-Mar-10 1:04
TechnologyIS19-Mar-10 1:04 
GeneralRe: Think hard before you use this software Pin
radioman.lt19-Mar-10 2:27
radioman.lt19-Mar-10 2:27 
GeneralRe: Think hard before you use this software Pin
TechnologyIS21-Mar-10 5:32
TechnologyIS21-Mar-10 5:32 
GeneralRe: Think hard before you use this software Pin
radioman.lt21-Mar-10 6:23
radioman.lt21-Mar-10 6:23 
GeneralRe: Think hard before you use this software PinPopular
Member 387010030-Apr-10 9:06
Member 387010030-Apr-10 9:06 
GeneralRe: Think hard before you use this software Pin
BloodyBaron4-Aug-11 9:59
BloodyBaron4-Aug-11 9:59 
GeneralRe: Think hard before you use this software Pin
radioman.lt4-Aug-11 10:18
radioman.lt4-Aug-11 10:18 
GeneralRe: Think hard before you use this software Pin
RyanEK3-Jun-10 14:36
RyanEK3-Jun-10 14:36 
GeneralRe: Think hard before you use this software Pin
Joe Sonderegger14-Jan-11 10:35
Joe Sonderegger14-Jan-11 10:35 
GeneralMy vote of 1 Pin
edmachad20-Feb-10 9:03
edmachad20-Feb-10 9:03 
GeneralRe: My vote of 1 Pin
radioman.lt6-Mar-10 10:14
radioman.lt6-Mar-10 10:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.