Display Google Maps for an address inside a form in C#


[Google Maps]

This was a lot easier until changes to Google Maps and the WebBrowser control added some rather annoying complications. The idea is simple. You use the techniques described in Display Google Maps for an address in C# to get a Google Maps URL and then make the WebBrowser navigate to it.

If you do only that, however, Google Maps displays this message:

You seem to be using an unsupported browser. Old browsers can put your security at risk, are slow and don’t work with newer Google Maps features. To access Google Maps, you’ll need to update to a modern browser.

This happens even if you have installed the latest version of Internet Explorer, which is what the WebBrowser uses.

Microsoft designed the WebBrowser control so it can emulate different versions of Internet Explorer. That way if you have an older application to support and it used Internet Explorer 7, you can make it work. I give Microsoft 10 bonus points for making this possible.

Unfortunately by default the WebBrowser emulates Internet Explorer 7, which is too old to support Google Maps. -2 bonus points for making the default be the oldest version instead of the newest.

To make matters worse, the way you tell the WebBrowser to emulate some other version of Internet Explorer is to modify the System Registry. It would have been a lot better if you could just set a property on the control. Another -5 points for making this so hard.

In fact the setting that you change in the Registry depends on the program you’re running so you can’t event change the setting for all of your programs at once. -2 more points.

That leaves Microsoft with only 1 bonus point: you can do this, but it’s tricky.

Believe it or not, there are still a few more complications for which I’m not even taking off points. It’s hard to figure out where to set the value in the Registry and it’s hard to figure out what value to use.

So here are the details.

If you are running a 32-bit program on a 64-bit system, you need to set this Registry value:

SOFTWARE\
    Wow6432Node\
        Microsoft\
            Internet Explorer\
                MAIN\
                    FeatureControl\
                        FEATURE_BROWSER_EMULATION\
                            app.exe

If you are running a 32-bit program on a 32-bit system, or if you are running a 64-bit program on a 64-bit system, you need to set this Registry value:

SOFTWARE\
    Microsoft\
        Internet Explorer\
            MAIN\
                FeatureControl\
                    FEATURE_BROWSER_EMULATION\
                        app.exe

Here app.exe is the name of the executable program that you are running.

That leads to another complication in a C# program. When you run in Visual Studio, the program isn’t actually the executable you might think it is. Instead it runs in a host application that is used by Visual Studio. For instance, the example program’s executable is howto_address_integrated_map.vshost.exe when you run it in Visual Studio but it’s howto_address_integrated_map.exe when you run it in standalone. That means the name of the Registry value that you need to set changes depending on whether you’re running inside Visual Studio.

You can place the value in any appropriate Registry hive. To minimize danger, I decided to do this in HKEY_CURRENT_USER.

You should set the value to a DWORD. There are several values that you can use. The simplest values are 7000, 8000, 9000, 10000, or 11000 to represent Internet Explorer 7, 8, 9, 10, or 11. You can see a more complete list of possible values in this MSDN article.

Yes, this is all pretty confusing. Fiddling with the Registry manually can be confusing and dangerous. You may do it wrong so the program won’t work, or you may mess up the Registry so something else breaks. Here’s how the example program handles the situation relatively safely.

The following SetRegistryDword method sets a value in the Registry.

// Set a registry DWORD value.
private void SetRegistryDword(string key_name,
    string value_name, int value)
{
    // Open the key.
    RegistryKey key =
        Registry.CurrentUser.OpenSubKey(key_name, true);
    if (key == null)
        key = Registry.CurrentUser.CreateSubKey(key_name,
            RegistryKeyPermissionCheck.ReadWriteSubTree);

    // Set the desired value.
    key.SetValue(value_name, value, RegistryValueKind.DWord);

    key.Close();
}

This method opens the Registry key with a particular name. If the key doesn’t exist, the method creates it.

The code then uses the key’s SetValue method to set the appropriate value. (The example also includes a DeleteRegistryValue method to make it easier to remove values for testing. Download the example for details.)

The following method creates the necessary Registry value to make the WebBrowser emulate a particular Internet Explorer version.

// Make the WebBrowser control emulate the indicated IE version.
// See:
//http://msdn.microsoft.com/library/ee330730.aspx#browser_emulation
private void SetWebBrowserVersion(int ie_version)
{
    const string key64bit =
        @"SOFTWARE\Wow6432Node\Microsoft\Internet Explorer\" +
        @"MAIN\FeatureControl\FEATURE_BROWSER_EMULATION";
    const string key32bit =
        @"SOFTWARE\Microsoft\Internet Explorer\MAIN\" +
        @"FeatureControl\FEATURE_BROWSER_EMULATION";
    string app_name = System.AppDomain.CurrentDomain.FriendlyName;

    // You can do both if you like.
    //SetRegistryDword(key64bit, app_name, ie_version);
    SetRegistryDword(key32bit, app_name, ie_version);
}

The code creates two strings holding the names of the keys that contain the values it might need to create. It then gets the executing program’s name, as in howto_address_integrated_map.exe. It then passes the appropriate key name, the app name, and the Internet Explorer version code into the SetRegistryDword method to set the value.

My system is running 64-bit Visual Studio in 64-bit Windows, but note that it doesn’t really hurt to set both Registry values to handle the other combinations.

When the program starts, it uses the following code to make the WebBrowser emulate Internet Explorer 11.

// Make the WebBrowser emulate Internet Explorer 11.
// Select a default map type.
private void Form1_Load(object sender, EventArgs e)
{
    SetWebBrowserVersion(11001);
    cboGoogle.SelectedIndex = 0;
}

Finally, the program uses the following code to display a map.

// Display a Google map.
private void btnGoogle_Click(object sender, EventArgs e)
{
    // Get the Google maps URL with defult zoom.
    string url = GoogleMapUrl(txtAddress.Text, cboGoogle.Text, 0);

    // Display the URL in the WebBrowser control.
    wbrMap.Navigate(url);
}

The code uses the GoogleMapUrl method described in the previous post to get the appropriate URL and then makes the WebBrowser navigate to it.


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in graphics, internet, system and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *