65.9K
CodeProject 正在变化。 阅读更多。
Home

通过桌面应用程序与 Google 地图集成

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.93/5 (9投票s)

2018 年 1 月 15 日

CPOL

4分钟阅读

viewsIcon

19062

如何通过基于 MFC 对话框的应用程序与 Google 地图集成

关于谷歌地图 API

根据谷歌地图 API 的“入门”页面,“谷歌地图 API 按平台分类:Web、Android 和 iOS。这些原生平台 API 由我们的 HTTP Web 服务套件提供补充。” 一如既往,尤其是在当今,你几乎找不到适用于 Windows 桌面应用程序的 API 代码示例,尤其是 C++ 的。

在 MFC 应用程序中托管 Web 浏览器

为了实现我的解决方案,你需要在你的 MFC 应用程序中托管一个 Web 浏览器

  1. 选择应用程序类型。

    打开 Visual C++ 并按照以下步骤操作

    1. 从“文件”菜单中选择“**新建**”。
    2. 选择“**MFC 应用程序向导(EXE)**”。
    3. 输入项目名称并选择一个位置。
    4. 点击**确定**。
    5. 当出现第 1 步的对话框时,选择适合你应用程序的应用程序类型——单文档、多文档或基于对话框。在本示例中,请选择“**基于对话框**”。
    6. 点击**下一步**。
  2. 选择应用程序功能和支持。

    第 2 步的对话框会询问你选择应用程序所需的功能和支持——例如,“**关于**”框或自动化支持。 **WebBrowser** 控件是一个 ActiveX 控件,因此请选择 ActiveX 控件。单击“**下一步**”进入下一步。

  3. 选择项目样式。

    第 3 步的对话框用于定义你的项目。你只有一个项目样式选项,标准 MFC。但是,你可以指示是否希望 IDE 在源代码中生成注释,并指定如何使用 MFC 库。默认选择适用于大多数应用程序。单击“**下一步**”进入下一步。

  4. 命名文件和类。

    第 4 步的对话框显示了 Visual C++ 创建的所有文件和类的名称。你可以将它们更改为更具描述性的名称,或更改为你的规范所需的名称。单击“**完成**”。

  5. 添加一个 **WebBrowser** 控件。

    现在你已经有了一个骨架应用程序。由于本示例使用的是基于对话框的应用程序,因此一个带有“**确定**”和“**取消**”按钮的对话框会出现在“**对话框编辑器**”中。按照以下步骤将 ActiveX 控件添加到对话框。

    1. 右键单击“**对话框编辑器**”。
    2. 从菜单中选择“**插入 ActiveX 控件**”。
    3. 选择“**Microsoft Web Browser**”。
    4. 点击**确定**。
    5. 在“**对话框编辑器**”中定位和调整 **WebBrowser** 控件的大小。
    6. 如果你的应用程序不需要默认的“**确定**”和“**取消**”按钮,请删除它们。
  6. 添加一个 WebBrowser 类和一个成员变量。

    当你插入一个 **WebBrowser** 控件时,会为其自动分配一个标识符,但你必须提供一个成员变量来访问该控件。要添加变量

    1. 右键单击 **WebBrowser** 控件。
    2. 选择“**类向导**”。
    3. 单击“**成员变量**”选项卡以显示控件标识符。
    4. 选择“**IDC_EXPLORER1**”。
    5. 单击“**添加变量**”,然后出现以下对话框

      Warning Message

    6. 单击“**确定**”以显示“**确认类**”对话框。
    7. 再次单击“**确定**”以将 CWebBrowser2 类添加到你的项目中。
    8. 为控件变量输入一个名称。

    现在你有一个包含浏览器的应用程序。但是,如果你编译 Visual C++ 生成的代码并运行可执行文件,浏览器不会出现。

获取你的谷歌地图 API

请阅读说明以获取你代码所需的 API KEY。

解决方案

首先定义一个全局变量

//
CExplorer1 m_Browser;
//

经过一些研究,我发现与谷歌地图交互最有效的方式是通过 WebBrowser 控件,而做到这一点的最佳方法是维护一个临时 HTML 文件,然后由 WebBrowser 控件打开。

我们将在此运行时使用此 HTML 文件,因此我们使用以下代码为其分配路径

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

第一个构建块将是一个用于生成(或更新)此文件的函数。

方法 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);
 }

方法 2

假设你已经定义了 Longitude Latitude 以及缩放级别(在我的示例中设置为“10”),并且已经获取了 API_KEY,你应该使用以下代码

        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 浏览器兼容性问题

最近,使用 WebBrowser 控件与谷歌地图等 API 进行接口变得更加困难。请阅读以下文章并按照其中的说明操作,当你尝试在 WebBrowser 控件中显示谷歌地图时会收到一条错误消息。

基本上,你需要修改以下注册表项

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

或者,添加 META 标记

IE X-UA-Compatible

显示地图

然后,当你希望在 WebBrowser 控件中显示谷歌地图时,只需调用

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

历史

  • 2018 年 1 月 15 日:初始版本
© . All rights reserved.