在 Bing 地图行程优化器示例中迁移现有代码

本文重点介绍在从 Bing 地图行程优化器的 ActiveX 版本迁移到 Windows 应用商店应用程序时所遵循的一些重要原则。本文档未完整说明如何将现有代码迁移至 Windows 运行时,但重点介绍了我们的经验以及必须牢记的重要事项。

备注

Bing 地图行程优化器示例(Windows 应用商店应用程序)和 Bing 地图行程优化器(ActiveX Web 应用程序)中提供了与本文对应的示例代码。

本文内容

  • JavaScript 迁移关键点

  • C++ 迁移关键点

  • 互操作性迁移关键点

JavaScript 迁移关键点

Bing 地图行程优化器的 ActiveX 版本对 UI 使用一个代码文件,即 OptimizerControl.htm。如本文档所述,当我们通过迁移使用 Windows 运行时时,必须为与 Web 交互的组件以及与 Windows 运行时交互的组件提供不同的上下文。我们必须编写额外代码才能在上下文之间进行通信。Features and restrictions by context一文更详细地说明了本地上下文与 Web 上下文之间的差异。

在 Windows 应用商店应用程序版本中,我们可以使用原始版本中的大部分代码。一个主要区别是,由于 Windows 应用商店应用程序不再引用 Activex 控件,我们用表示 C++ 组件的全局变量替换了 object 元素。在 Bing 地图行程优化器示例中的 JavaScript 和 C++ 之间进行互操作中对此机制进行了详细说明。

Window 方法(如 alertpromptopen)在 JavaScript Windows 应用商店应用程序中不起作用。控件的 ActiveX 版本使用 alert 向用户通知问题(如输入的位置超过了 25 个)。应用程序的 Windows 应用商店版本使用 Windows.UI.Popups.MessageDialog 类向用户显示消息。

// Show message dialog.            
new Windows.UI.Popups.MessageDialog(data.message).showAsync().then();

由于没有要在消息对话框显示之后执行的操作,因此 then 语句为空。有关在 JavaScript 中如何使用异步操作的详细信息,请参见Asynchronous programming

有关与如何在 JavaScript Windows 应用商店应用程序中使用现有 HTML 功能的某些区别的详细信息,请参见 HTML, CSS, and JavaScript features and differences

该应用程序的 ActiveX 版本使用 Bing 地图 AJAX 控件版本 6.3 在 UI 中显示地图。Windows 应用商店应用程序版本使用 Bing 地图 AJAX 控件版本 7.0。不要求从版本 6.3 升级到版本 7.0;可在 Windows 应用商店应用程序中使用版本 6.3。我们在此实现中选择了版本 7.0,因为它包含性能改进和改进的触摸支持,并且我们要演示从 Bing 地图获取信息的新方法。

[顶部]

C++ 迁移关键点

使用 C++/CX 创建 Windows 应用商店组件时,由编译器和 Windows 运行时处理与其他组件和语言互操作所需的基础结构。将控件的 ActiveX 版本迁移至 Windows 应用商店组件时,可删除实现自定义 COM 接口所需的基础结构代码。例如,Windows 运行时组件不需要 IDL 文件来定义组件所提供的接口和事件。此外,我们还尽可能维护了使用纯本机代码的实现详细信息。仅当控件与其他 Windows 运行时对象和组件进行交互时,才需要使用 C++/CX 和 Windows 运行时。

在将 Activex 控件迁移到使用 Windows 运行时的控件时,请考虑以下准则。

提示

其中许多准则都涉及使用 C++/CX 语法。有关此语法的详细信息,请参见 Visual C++ 语言参考 (C++/CX)

  • 使用**“WinRT 类库”**模板创建 Visual Studio 项目。

  • 将公共接口方法和属性从 Activex 控件添加至 Windows 运行时类。转换参数和返回类型,以便使用与 Windows 运行时兼容的类型。例如,TripOptimizerImpl.idl 定义用于 Activex 控件的 IOptimizerControl 接口。

    interface IOptimizerControl : IDispatch{
       [id(1)] HRESULT OptimizeTripAsync([in] VARIANT* waypoints, [in] BSTR travelMode, 
          [in] BSTR optmz, [in] BSTR bingMapsKey,
          [in] DOUBLE alpha, [in] DOUBLE beta, [in] DOUBLE rho, [in] ULONG iterations,
          [in] VARIANT_BOOL parallel);
       [id(2)] HRESULT CancelAsync();
    };
    

    对于 Windows 应用商店组件,此处是 Windows 运行时组件中 TripOptimizer::OptimizeTripAsync 方法的声明。我们使用实际返回类型 Windows::Foundation::Collections::IMap<K, V>,而不是 HRESULT。我们还对每个参数使用适当的 Windows 运行时类型。

    备注

    由于 Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>::Cancel 方法提供了取消功能,因此我们可以移除此实现中的 CancelAsync 方法。

    // Optimizes a trip as an asynchronous process.
    Windows::Foundation::IAsyncOperationWithProgress<
        Windows::Foundation::Collections::IMap<
            Platform::String^, 
            Windows::Foundation::Collections::IVector<Platform::String^>^>^, 
        Platform::String^>^ OptimizeTripAsync(
            Windows::Foundation::Collections::IVector<Platform::String^>^ waypoints, 
            Platform::String^ travelMode, 
            Platform::String^ optimize,
            Platform::String^ bingMapsKey, 
            double alpha, double beta, double rho,
            unsigned int iterations, bool parallel);
    

    创建 TripOptimizer 和 TripOptimizerImpl 类部分详细说明了 TripOptimizer::OptimizeTripAsync 方法。

  • 将公共事件从 Activex 控件添加至 Windows 运行时类。转换参数和返回类型,以便使用与 Windows 运行时兼容的类型(与方法和属性一样)。

    在此实现中,我们可以移除在 ActiveX 版本中定义的所有事件,因为这些操作均通过其他方式来处理。例如,由于可以直接在 TripOptimizer::OptimizeRouteAsync 返回的 IAsyncOperationWithProgress<TResult, TProgress> 对象中返回结果,因此我们不必再定义完成事件。错误和进度回调也由 IAsyncOperationWithProgress<TResult, TProgress> 对象来处理。有关应用程序的 JavaScript 部分如何使用异步操作的详细信息,请参见在 Bing 地图行程优化器示例中的 JavaScript 和 C++ 之间进行互操作

  • 在为 Windows 运行时类定义数据成员时,请选择适当的标准 C++ 和 Windows 运行时类型。

    例如,COptimizerControl 类使用 COM 类型(如 _bstr_t)保存字符串值。

    在应用程序的 Windows 应用商店版本中,我们使用了 std::wstring(即标准 C++ 字符串类型)容纳字符串值。例如,在 TripOptimizerImpl::OptimizeTripAsync 方法中,我们将 Windows::Foundation::Collections::IVector<T>Platform::String 参数转换为 std::vectorstd::wstring,因为这些变量不传递回 Windows 运行时组件。

    // Copy inputs to a OptimizeTripParams structure.
    auto params = make_shared<OptimizeTripParams>();
    for (auto waypoint : waypoints)
    {
        params->Waypoints.push_back(waypoint->Data());
    }
    params->TravelMode = wstring(travelMode->Data());
    params->Optimize = wstring(optimize->Data());
    params->BingMapsKey = UriEncode(bingMapsKey->Data());
    params->Alpha = alpha;
    params->Beta = beta;
    params->Rho = rho;
    params->Iterations = iterations;
    params->Parallel = parallel;
    

    在使用此约定时,可以更明确地区分哪些变量用于 Windows 运行时。Windows 运行时 与您的代码进行定期通信时,Windows 运行时字符串和集合类型(如 Windows::Foundation::Collections::IMap<K, V>Windows::Foundation::Collections::IVector<T>)很有用,因为可减少应用程序必须进行的字符串类型转换的次数。在其他情况下,可考虑是否使用标准 C++ 集合类型,如 std::mapstd::vector

    组件工作流部分详细介绍了控件的实现详细信息。

  • 使用 Windows::Foundation::IAsyncActionWindows::Foundation::IAsyncActionWithProgress<TProgress>Windows::Foundation::IAsyncOperation<TResult>Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress> 接口可帮助定义异步方法。从 C++ Windows 应用商店应用程序或组件创建这些对象时,建议使用 concurrency::create_async函数方法。

  • 请尽量使用现有代码。我们只需修改少量代码或无需进行任何代码修改,即可迁移实现详细信息,例如蚁群优化算法。但是,由于 Windows 应用商店应用程序可以使用 Win32 和 COM API 的子集,因此必须对该组件的某些部分使用替代机制。例如,控件的 ActiveX 版本使用 IXMLHTTPRequest 与 HTTP 服务器通信。在 C++ 组件中,我们使用 IXMLHTTPRequest2,在 Windows 应用商店应用程序中与 HTTP 服务器通信时,建议使用此方法。为了处理来自 Bing 地图的 XML 响应,Activex 控件使用 XmlLite。在 Windows 应用商店组件中,我们使用 Windows 运行时 XmlDocument 类,因为它易于使用,并且我们要演示如何更新现有 COM 代码以使用 Windows 运行时类型。但是,如果 Windows 应用商店应用程序中已有 Win32 或 COM 代码,则可继续使用该代码。

    有关如何在 Windows 应用商店应用程序中使用 Win32 和 COM 的详细信息,请参见用于 Windows 应用商店应用程序的 Win32 和 COM

    重要

    如果在 Windows 应用商店应用程序中使用 Win32 和 COM,则该应用程序可在开发环境中运行,但不能批准其用于从 Windows 应用商店中分发。因此,建议经常运行应用程序验证工具,以确保应用程序通过验证。有关详细信息,请参见为 Windows 应用商店准备应用程序如何:安装、验证和上载包

  • Visual C++ 项目现在使用 pch.h 和 pch.cpp 保存预编译的头信息。将相关 #include 语句从 stdafx.h 迁移到 pch.h。

[顶部]

互操作性迁移关键点

在 Bing 地图行程优化器的 Windows 应用商店应用程序版本中,我们能够使用 ActiveX 版本中的大部分 JavaScript 代码。主要区别在于 HTML 和 JavaScript 代码引用 C++ 组件的方式。

ActiveX 版本使用 HTML object 标记引用 C++ 组件。

<object id="OptimizerControl" name="OptimizerControl" classid="CLSID:10FFAAB9-0E73-4C4D-8118-6225C7F2E692"></object>

相应地,ActiveX 版本使用 id 值“OptimizerControl”来调用 COptimizerControl 方法。

Bing 地图行程优化器的 Windows 应用商店应用程序版本设置项目引用,并使用全局变量而非 object 标记。项目系统执行 JavaScript 应用程序所需的步骤来查找和加载 C++ 组件。用 C++ 创建 Windows 运行时组件一文详细说明了如何设置项目引用。

ActiveX 版本使用 :: 语法来处理事件。

// Event handler for progress notifications from the control.
function document.OptimizerControl::ProgressCallback(message) {
   // Set message.
   ProgressMessageText.innerHTML = message;
}

Windows 应用商店应用程序版本使用异步处理和承诺对来自 C++ 组件的响应做出反应。接收来自 C++ 组件的数据部分介绍了此过程。

[顶部]