Click here to Skip to main content
13,800,885 members
Click here to Skip to main content
Add your own
alternative version

Tagged as

Stats

6.9K views
14 bookmarked
Posted 15 Jan 2018
Licenced CPOL

Integrating with Google Maps via a Desktop Application

, 15 Jan 2018
Rate this:
Please Sign up or sign in to vote.
How to integrate with Google Maps via an MFC dialog based application

Introduction

A while ago we were asked to create a small Desktop application that will go over photos and extract any Meta Data from them, including the location where each photo was taken (which is a topic for a separate article),. To display the result, I looked for a way to display a map, powered by Google Maps, in an MFC application. Here is the solution I have found.

About Google Maps API

According to the Google Maps API "Getting Started" page, "Google Maps APIs are categorized by platform: Web, Android and iOS. These native platform APIs are complemented by our suite of HTTP web services.". As usual, especially these days, you almost never found API code samples for Windows Desktop application, and especially c++ ones. 

Hosting a Web Browser in an MFC application

In order to implement my solution, you would need to host a Web Browser in your MFC application:

  1. Choose an application type.

    Open Visual C++ and follow these steps:

    1. Choose New from the File menu.
    2. Select MFC AppWizard (exe).
    3. Enter the project name and select a location.
    4. Click OK.
    5. When the dialog box for Step 1 appears, select the application type that is appropriate for your application—single document, multiple document, or dialog-based. Select "Dialog-based" for this example.
    6. Click Next.
  2. Select application features and support.

    The dialog box for Step 2 asks you to select any features and support your application will need—an About box or automation support, for example. The WebBrowser control is an ActiveX control, so select ActiveX Controls. Click Next to go to the next step.

  3. Select the project style.

    The dialog box for Step 3 is used to define your project. You have only one project style option, Standard MFC. But you can indicate whether you want the IDE to generate comments in the source code, and you can specify how you want to use the MFC library. The default selections are appropriate for most applications. Click Next to go to the next step.

  4. Name the files and classes.

    The dialog box for Step 4 displays the names of all the files and classes that Visual C++ created. You can change these to more descriptive names or to names required by your specification. Click Finish.

  5. Add a WebBrowser control.

    You now have a skeleton application. Because this example uses a dialog-based application, a dialog box with OK and CANCELbuttons appears in the Dialog Editor. Follow these steps to add an ActiveX control to the dialog box.

    1. Right-click the Dialog Editor.
    2. Select Insert ActiveX Control from the menu.
    3. Select Microsoft Web Browser.
    4. Click OK.
    5. Position and size the WebBrowser control in the Dialog Editor.
    6. Delete the default OK and CANCEL buttons if your application does not require them.
  6. Add a WebBrowser class and a member variable.

    When you insert a WebBrowser control, an identifier for the control is automatically assigned, but you must provide a member variable to access the control. To add a variable:

    1. Right-click the WebBrowser control.
    2. Select ClassWizard.
    3. Click the Member Variables tab to display the control identifiers.
    4. Select IDC_EXPLORER1.
    5. Click Add Variable, and the following dialog box appears:

      Warning Message

    6. Click OK to display a Confirm Classes dialog box.
    7. Click OK again to add a CWebBrowser2 class to your project.
    8. Enter a name for the control variable.

    You now have an application containing a browser. However, if you compile the code generated by Visual C++ and run the executable file, a browser does not appear.

Obtain your Google Maps API

Please read the instructions to obtain your API KEY which will be needed for this code.

The Solution

First define a global variable

//
CExplorer1 m_Browser;
//

After conducting some research I have found out that the most efficient way to inretact with Google Maps, would be via a WebBrowser control, and the best way of doing so, is to maintain a temporary HTML file which will then be opened by the WebBrowser control.

We will be using this HTML file during runtime, so we assign its path using the following code:

wchar_t FileName[2048];
GetCurrentDirectory(2048, FileName);
wcscat(FileName, L"\\test.html");

The first building block would be a function for generating (or updating) this file.

Method 1:

void WriteHTML(const wchar_t* html)
{
   IDispatch* pHtmlDoc = m_Browser.get_Document();
   if (!pHtmlDoc)
       return;
   CComPtr<IHTMLDocument2> doc1 = NULL;
   doc1.Detach();
   doc1.Attach((IHTMLDocument2*)pHtmlDoc);
   if (!doc1)
       return;

   // Creates a new one-dimensional array
   SAFEARRAY* psaStrings = SafeArrayCreateVector(VT_VARIANT, 0, 1);
   if (!psaStrings)
       return;

   BSTR bstr = SysAllocString(html);
   if (bstr)
   {
       VARIANT* param;
       HRESULT hr = SafeArrayAccessData(psaStrings, (LPVOID*)&param);
       if (SUCCEEDED(hr))
       {
           param->vt = VT_BSTR;
           param->bstrVal = bstr;
           hr = SafeArrayUnaccessData(psaStrings);
           if (SUCCEEDED(hr))
           {
               doc1->write(psaStrings);
               doc1->close();
           }
       }
   }

   // SafeArrayDestroy calls SysFreeString for each BSTR!
   if (psaStrings)
       SafeArrayDestroy(psaStrings);
 }

Method 2:

Assuming you have defined the Longitude and the Latitude along with the level of Zoom (set to "10" in my example), and obtained the API_KEY, you should use the following code:

CoInitialize(NULL);
m_Browser.put_Silent(TRUE);
CString HTML_TEXT;
CRect rect;
CWnd *pWnd = GetDlgItem(IDC_SGWEBBROWSER);
pWnd->GetWindowRect(&rect);
int w = rect.Width()-50, h = rect.Height()-50;

HTML_TEXT.Format(L"<!DOCTYPE html><html><meta http-equiv=\"IE X-UA-Compatible\" content=\"IE = edge\"><body><div id =\"googleMap\" style=\"width:%dpx;height:%dpx\"><script>function myMap(){var mapProp = {center:new google.maps.LatLng(%f, %f), zoom : 10};var map = new google.maps.Map(document.getElementById(\"googleMap\"), mapProp);marker = new google.maps.Marker({position: new google.maps.LatLng(%f, %f),map: map});}</script><script src = \"https://maps.googleapis.com/maps/api/js?key=%s&callback=myMap\"></script></div></body></html>", w, h, Latitude, Longitude, Latitude, Longitude, API_KEY);

FILE *fp = _wfopen(FileName, L"w");
fwprintf(fp, L"%s", HTML_TEXT.GetBuffer());
fclose(fp);
m_Browser.Navigate(FileName, 0, 0, 0, 0);

Web Browser Compatability Issues

Recently it became harder to use the WebBrowser control for interfacing with APIs such as Google Maps. Read the following article and following the instructions there is you get an error message when trying to display a Google Map in the WebBrowser control.

Basically, you need to manipulate the following Registry key:

Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Internet Explorer\Main\FeatureControl\FEATURE_BROWSER_EMULATION

Alternatively, add the META TAG 

IE X-UA-Compatible

Displaying the map

Then, when you wish to display the Google Map in your WebBrowser control, you just call:

m_Browser.Navigate(FileName, 0, 0, 0, 0);

.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Michael Haephrati
CEO Secured Globe, Inc.
United States United States
Michael Haephrati, CEO and co-founder of Secured Globe, Inc. Worked on many ventures starting from HarmonySoft, designing Rashumon, the first Graphical Multi-lingual word processor for Amiga computer. During 1995-1996 he worked as a Contractor with Apple at Cupertino.



You may also be interested in...

Pro

Comments and Discussions

 
-- There are no messages in this forum --
Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web05 | 2.8.181215.1 | Last Updated 15 Jan 2018
Article Copyright 2018 by Michael Haephrati
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid