Click here to Skip to main content
Click here to Skip to main content

Embedding Google Earth in a C# Application

By , 8 Dec 2008
 

Introduction

If you're interested in utilizing the Google Earth viewer as a control in a custom application, then continue reading. There are quite a few links around the Internet that provide information as to how to add references to your project, create a ApplicationGE, and control the Google Earth application. However, most of these tutorials do not focus on the details of embedding Google Earth in an application. That's what I will focus on here. From now on, GE means Google Earth.

The Code

You'll probably start off on your embedding adventure much like I did, with:

EARTHLib.ApplicationGE ge = new ApplicationGEClass();

If the GE process already exists, we will obtain a reference to it; if not, a new process will be created, and you would see the GE logo flash on the screen while loading. You will then see the main Google Earth screen with the embedded viewer. Since we are interested in embedding GE, we are not interested in having the main screen around, so we hide it!

ShowWindowAsync(ge.GetMainHwnd(), 0);

For all intensive purposes, we now have an empty screen. What we'd like to do next is embed the scene that GE renders into our application. We accomplish this by setting the render Hwnds parent to that of the window we would like to render to:

SetParent(ge.GetRenderHwnd(), this.Handle.ToInt32());

In the example above, 'this' is a Windows Form. The end result, if you perform these same steps, should look similar to the image below, although I do warn that results may vary :-)

google_earth_embedded.jpg

You will notice that resizing the window has no effect on the scene. If you plan on embedding GE in an application for any useful purposes, you'll most likely need it to respond to resizing. I spent a bit of time sniffing into the events that were passed to the scene when I performed re-size of the main GE application window. This led me to a special event, WM_QT_PAINT, in addition to a sequence of others. It took a bit of tinkering to get it all right, but this appeared to work for me:

SendMessage(ge.GetMainHwnd(), WM_COMMAND, WM_PAINT, 0);
PostMessage(ge.GetMainHwnd(), WM_QT_PAINT, 0, 0);
SetWindowPos( ge.GetMainHwnd(), HWND_TOP, 0, 0, (int)this.Width, 
             (int)this.Height, SWP_FRAMECHANGED);
SendMessage(ge.GetRenderHwnd(), WM_COMMAND, WM_SIZE, 0);

This should allow the scene to adjust according to the parent form's size. I bundled this up into a method named "ResizeGoogleControl", and called it after SetParent and within my Form_Resize event. The results are illustrated in this image:

google_earth_embedded_good.jpg

The Example

I slapped together a test app that you are welcome to use for reference. If you have any comments or suggestions, be sure to send me an email or add a comment. Create a new C# project in Visual Studio and replace the Form1.cs code with this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

using EARTHLib;

namespace resize_google_earth
{

public partial class Form1 : Form
{
    [DllImport("user32.dll")]
    private static extern int SetParent(
    int hWndChild,
    int hWndParent);

    [DllImport("user32.dll")]
    private static extern bool ShowWindowAsync(
    int hWnd,
    int nCmdShow);

    [DllImport("user32.dll", SetLastError = true)]
    private static extern bool PostMessage(
    int hWnd,
    uint Msg,
    int wParam,
    int lParam);

    [DllImport("user32.dll", EntryPoint = "SetWindowPos")]
    private static extern bool SetWindowPos(
    int hWnd,
    int hWndInsertAfter,
    int X,
    int Y,
    int cx,
    int cy,
    uint uFlags);

    [DllImport("user32.dll")]
    private static extern int SendMessage(
    int hWnd,
    uint Msg,
    int wParam,
    int lParam);

    private const int HWND_TOP = 0x0;
    private const int WM_COMMAND = 0x0112;
    private const int WM_QT_PAINT = 0xC2DC;
    private const int WM_PAINT = 0x000F;
    private const int WM_SIZE = 0x0005;
    private const int SWP_FRAMECHANGED = 0x0020;

    public Form1()
    {
        InitializeComponent();

        ge = new ApplicationGEClass();

        ShowWindowAsync(ge.GetMainHwnd(), 0);
        SetParent(ge.GetRenderHwnd(), this.Handle.ToInt32());
        ResizeGoogleControl();
    }

    private void Form1_Resize(object sender, EventArgs e)
    {
        ResizeGoogleControl();
    }

    private void ResizeGoogleControl()
    {
        SendMessage(ge.GetMainHwnd(), WM_COMMAND, WM_PAINT, 0);
        PostMessage(ge.GetMainHwnd(), WM_QT_PAINT, 0, 0);

        SetWindowPos(
        ge.GetMainHwnd(),
        HWND_TOP,
        0,
        0,
        (int)this.Width,
        (int)this.Height,
        SWP_FRAMECHANGED);

        SendMessage(ge.GetRenderHwnd(), WM_COMMAND, WM_SIZE, 0);
    }

    private EARTHLib.ApplicationGE ge = null;
}
}

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

About the Author

Joseph Armbruster
Software Developer
United States United States
Member
I love to write programs and vim is my editor of choice. Programming languages fascinate me and I feel at least reasonably familiar with C, python, C++, JAVA, C#, ECMAScript, Lua and Ruby. I also use a few open source relational database systems; postgresql, mysql, sqlite. Some of my interests include: programming languages, geoprocessing, number theory, network protocols, web services, cryptography, linux, windows, open source, GIS.
 
See: http://www.joevial.com

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionForm not loading Google EarthmemberMember 842394629 Apr '13 - 10:09 
Sir, I am using Windows 7 OS with Visual Studio 2012 Express. When I launch the program, Google Earth screen pops up in a stand alone screen, then disappears, with my form blank. Can you please provide me with some guidance on what I am doing wrong? Thank you!!
QuestionAdd GPSmember3nZo23 Apr '13 - 1:37 
hi
Thanks alot for the nice article
 
How may i add GPS to it? i mean how may i access to Tools << GPS in google earth ?
 
also other functionality of google earth such as Flight Simulator ,....
QuestionDear Sir,memberEthiopaninomaltt23 Feb '13 - 2:51 
I have seen your code and it is great.but i face a problem of Earthlib referece.please send to my g-mail "ethiogt.gt@gmail.com" because i haven't get any file to download from the Internet. also provide the procedure whether it need to install Google earth software in that computer.
QuestionHow to get Coordiantes from cursormemberM.S.S.E21 Jan '13 - 23:57 
I'm using
GetPointOnTerrainFromScreenCoords(0, 0);
Method to get the coordinates from the center of the screen, but I need to get them from the cursor as it moves, ant solution?
Much thanks.
QuestionWPF CompatibiltymemberMember 960766617 Nov '12 - 8:23 
Hello there,
Just wondering if this would be compatible in WPF application? If not, does any one know of any alternatives?
 
Cheers
QuestionThis demo just open once , GE dont run in secondmembershindo2165 Sep '12 - 17:48 
I run your demo successfull in the first , but if I run again the GE dont display , I must open task manager ,and end process googleeath.exe .
Do you have any solution for my issue ?
Thanks and best regards
AnswerRe: This demo just open once , GE dont run in secondmembershindo2165 Sep '12 - 18:21 
I have solved this issue , I used library system.diagnostics and class process to kill process "googleearth.exe"
GeneralRe: This demo just open once , GE dont run in secondmemberraddog14 Jan '13 - 12:54 
Try:
 
 PostMessage(ge.GetMainHwnd(), WM_QUIT, 0, 0);
 
where ge is your instance of ApplicationGEClass
Mongo Programmer

QuestionMouse wheel zoom in/out doesn't work? [modified]membersherifffruitfly23 Aug '12 - 18:40 
What's the issue here - anybody know?
 
Also, the form-resize doesn't result in GE resizing. Nevermind. Forgot to bind the code to the event. durr.
 
Lastly, I had to put in a kill-GE-process on application exit, ensure it got disposed.
 
Now I need to figure out how to feed a KML file to this embed.
 
thanks for getting me started tho!
-sff

modified 24 Aug '12 - 0:47.

Questionplace mark iconmembermojimoj18 Mar '12 - 8:52 
hello, is there a method to when i click in a place, a placemark icon put in that place?
like GEtoolbar. or is it possible to use GEtoolbar in yout app?
excuse me for my bad EN language!
QuestionHimembermyazar16 Nov '11 - 9:31 
Hi Joseph,
 
Thanks for your sharing.
 
I downloaded your code and i ran in Microsoft Visual Studio 2010 but i am getting the following error.
 
ERROR:-
 
Retrieving the COM class factory for component with CLSID {8097D7E9-DB9E-4AEF-9B28-61D82A1DF784} failed due to the following error: 80040154.
 
Could you please help me about this problem.
 
Thanks
GeneralMy vote of 4memberspicolihill@hotmail.com27 May '11 - 11:44 
Clean code that shows the basics! good job Joe
Generalx64 (64bit) machinesmemberth3_v0ice1 May '11 - 6:10 
For everyone that are compiling this code on 64bit machine it won't work until you change it to compile for 32bit processor (x86)
GeneralInitializeComponent()membernat0626 Jan '11 - 21:00 
Hi,
 
Where can I find the InitializeComponent()function in this code, I can't see the definition for it. It is only called, but I got an error for its definition.
 
Also I would like to ask how can I use this code with asp.net web application?
I would appreciate your help a lot.
 
Thank you very much in advance.
GeneralRe: InitializeComponent()memberRayChenMedical21 Apr '11 - 6:25 
I am using VS 2010, you can go to 2 files
1.AssemblyInfo.cs
change [assembly: AssemblyTitle("WindowsApplicationForm1")] to
[assembly: AssemblyTitle("resize_google_earth")]
and [assembly: AssemblyProduct("WindowsApplicationForm1")] to
[assembly: AssemblyTitle("resize_google_earth")]
 
2.Program.cs
change namespace from WindowsApplicationForm1 resize_google_earth.
 
It might work for you
 
Ray
GeneralEARTHLib;membermostafa.elsadany7 Jan '11 - 4:28 
EARTHLib;
 
where i find that
GeneralRe: EARTHLib;memberfosterz3 Feb '11 - 19:34 
hey buddy, did you find this EARTHLib, then please let me know where can i find that
GeneralRe: EARTHLib;memberMarkyMark7831 Dec '11 - 0:32 
Add a reference to googleearth.exe (e.g. C:\Program Files (x86)\Google\Google Earth\client\googleearth.exe)
 
This will give you EARTHLib under references, select it and change "Embed Interop Types" to false then use above code.
 
Also ensure application is x86 (not 64 bit).
GeneralMy vote of 5membercrazycoding20 Dec '10 - 1:05 
Great! I have been looking for
such a project for long time. It works very well.
QuestionChange the rendering sizemembersdecorme6 Dec '10 - 23:17 
Hi
Great code works fine .
On my winform I need to resize GE to (236,177) for example because I have another thing on my form how can I do this ?
Thanks
General[Help]how can close KML files.memberevhunter25 Nov '10 - 4:19 
HI:
I embed Google Earth in my C# programme, and I used OpenKmlFile ([in] BSTR fileName,[in] BOOL suppressMessages) to land placemarks into programme.
Now, I want to know that how can I close or delete these placemarks in the Form?
Who can give me some code?
GeneralMy vote of 5memberAbhinav S22 Oct '10 - 6:40 
Nice.
QuestionHow to get to a particular latitude and longitudememberhemshankarsahu20 Oct '10 - 20:37 
Hi.
 
In my project i want to embed it idea of showing the google earth screen.
 
What I want is that i will the user of the project will have a test box for entering the latitude and longitude and on pressing enter the from should show the appropriate palce
 
Also if possibe the searching by name of a place is to be embedded.
 
Zoom in and Zoom out is also required.
 
Can u tell any method to do so.
 

THank You
 
Hemshankar Sahu
AnswerRe: How to get to a particular latitude and longitudemembersdecorme6 Dec '10 - 23:20 
You can do like this
 
double lat = 44.39165;
double lon = 4.71157;
double alt = 1000;
AltitudeModeGE AltiGe = AltitudeModeGE.AbsoluteAltitudeGE;
double range = 100;
double tilt = 0;
double azimuth = 0;
double speed = 5;
 
ge.SetCameraParams(lat, lon, alt, AltiGe, range, tilt, azimuth, speed);
 
More information here
 
http://earth.google.com/comapi/interfaceIApplicationGE.html#9e1c8da5b36e8687fe718f2267224103
 
Good Luck
GeneralMy vote of 5membergvmohanraj13 Oct '10 - 22:59 
This provided me what I was looking for

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

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130516.1 | Last Updated 8 Dec 2008
Article Copyright 2008 by Joseph Armbruster
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid