Compartir a través de


Migrar código existente en el ejemplo de Bing Maps Trip Optimizer

En este documento se destacan algunas de las instrucciones clave que seguimos cuando migramos desde la versión ActiveX de Organizador de recorridos de Mapas de Bing a una aplicación de la Tienda Windows. Este documento no proporciona una explicación completa de cómo migrar el código existente a Windows en tiempo de ejecución. En su lugar, resalta nuestra experiencia y los aspectos importantes que tuvimos que tener en cuenta.

NotaNota

El código de ejemplo correspondiente a este documento se encuentra en el ejemplo de Optimizador de recorridos de Mapas de Bing (aplicación de Tienda Windows) y Optimizador de recorridos de Mapas de Bing (aplicación web ActiveX).

En este artículo

  • Puntos clave de migración de JavaScript

  • Puntos clave de migración de C++

  • Puntos clave de migración de interoperabilidad

Puntos clave de migración de JavaScript

La versión de ActiveX de Optimizador de recorridos de Mapas de Bing utiliza un archivo de código, OptimizerControl.htm, para la interfaz de usuario. Como se describe en esta documentación, cuando migramos para utilizar Windows en tiempo de ejecución, tuvimos que crear contextos independientes para los componentes que interactúan con la Web y los que interactúan con Windows en tiempo de ejecución. Tuvimos que escribir código adicional para permitir que los contextos se comunicasen. El documento Features and restrictions by context contiene más explicaciones sobre las diferencias entre los contextos local y web.

Pudimos usar la mayor parte del código de la versión original en la versión de la aplicación de la Tienda Windows. Una diferencia principal es que, dado que la aplicación de la Tienda Windows ya no hace referencia a un control ActiveX, reemplazamos el elemento object por una variable global que representa el componente de C++. Este mecanismo se explica con más detalle en Interoperar entre JavaScript y C++ en el ejemplo de Bing Maps Trip Optimizer.

Los métodos de ventana como alert, prompt y open no funcionan en aplicaciones de la Tienda Windows de JavaScript. La versión de ActiveX del control utiliza alert para informar al usuario de un problema, por ejemplo cuando se han escrito más de 25 ubicaciones. La versión de Tienda Windows de la aplicación utiliza la clase Windows.UI.Popups.MessageDialog para mostrar mensajes al usuario.

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

Dado que no hay ninguna acción para realizar después de que se muestre el cuadro de diálogo de mensajes, la instrucción then está vacía. Para obtener más información sobre cómo trabajar con operaciones asincrónicas en JavaScript, consulta Asynchronous programming.

Para obtener más información sobre algunas de las diferencias de cómo se usan las funciones HTML existentes en una aplicación de la Tienda Windows de JavaScript, consulta HTML, CSS, and JavaScript features and differences.

La versión de ActiveX de la aplicación utiliza la versión 6.3 de Control AJAX de Mapas de Bing para mostrar el mapa en la interfaz de usuario. La versión de la aplicación de Tienda Windows utiliza la versión 7.0 de Control AJAX de Mapas de Bing. La actualización de la versión 6.3 a la versión 7.0 no era un requisito; puedes usar la versión 6.3 en una aplicación de la Tienda Windows. Elegimos la versión 7.0 de esta implementación porque incluye mejoras de rendimiento y de compatibilidad para entrada táctil, y deseamos mostrar la forma más actual de obtener información de Mapas de Bing.

[Principio]

Puntos clave de migración de C++

Cuando usas C++/CX para crear componentes de la Tienda Windows, el compilador y Windows en tiempo de ejecución controlan la infraestructura necesaria para interactuar con otros componentes y lenguajes. Cuando migramos la versión ActiveX del control a un componente de la Tienda Windows, podíamos quitar el código de infraestructura necesario para implementar una interfaz COM personalizada. Por ejemplo, un componente de Windows en tiempo de ejecución no requiere archivos IDL que definan las interfaces y los eventos que un componente proporciona. Además, mantuvimos los detalles de implementación que utilizan código nativo puro cuando pudimos. El uso de C++/CX y de Windows en tiempo de ejecución solo se requiere cuando el control interactúa con otros objetos y componentes de Windows en tiempo de ejecución.

Considera estas instrucciones sobre cómo migrar tus controles ActiveX a controles que utilizan Windows en tiempo de ejecución.

SugerenciaSugerencia

Muchas de estas instrucciones implican trabajar con la sintaxis de C++/CX.Para obtener más información acerca de esta sintaxis, consulta Referencia del lenguaje Visual C++ (C++/CX).

  • Utiliza la plantilla Biblioteca de clases de WinRT para crear el proyecto de Visual Studio.

  • Agregue los métodos y propiedades de interfaz pública del control ActiveX a tu clase Windows en tiempo de ejecución. Convierte el parámetro y los tipos de valor devuelto para que usen tipos compatibles con Windows en tiempo de ejecución. Por ejemplo, TripOptimizerImpl.idl define la interfaz IOptimizerControl para el control ActiveX.

    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();
    };
    

    Para el componente de la Tienda Windows, aquí se presenta la declaración del método TripOptimizer::OptimizeTripAsync en el componente de Windows en tiempo de ejecución. Utilizamos el tipo de valor devuelto real, Windows::Foundation::Collections::IMap<K, V>, en lugar de HRESULT. También utilizamos el tipo de Windows en tiempo de ejecución adecuado para cada parámetro.

    NotaNota

    Podríamos quitar el método CancelAsync en esta implementación porque la funcionalidad de cancelación la proporciona el método Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress>::Cancel.

    // 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);
    

    El método TripOptimizer::OptimizeTripAsync se explica con más detalle en la sección Crear las clases TripOptimizer y TripOptimizerImpl.

  • Agrega los eventos públicos del control ActiveX a tu clase de Windows en tiempo de ejecución. Al igual que sucede con los métodos y propiedades, deber convertir los tipos de parámetro y de valor devuelto para que usen tipos compatibles con Windows en tiempo de ejecución.

    En esta implementación, pudimos quitar todos los eventos que se definieron en la versión de ActiveX porque todas estas acciones se controlan con otros medios. Por ejemplo, ya no tenemos que definir un evento de finalización porque devolvemos el resultado directamente como parte del objeto IAsyncOperationWithProgress<TResult, TProgress> que devuelve TripOptimizer::OptimizeRouteAsync. Las devoluciones de llamada de error y progreso también las controla el objeto IAsyncOperationWithProgress<TResult, TProgress>. Para obtener más información sobre cómo la parte de JavaScript de la aplicación utiliza la operación asincrónica, consulta Interoperar entre JavaScript y C++ en el ejemplo de Bing Maps Trip Optimizer.

  • Elige el C++ estándar y los tipos de Windows en tiempo de ejecución apropiados cuando definas miembros de datos para tu clase Windows en tiempo de ejecución.

    Por ejemplo, la clase COptimizerControl utiliza tipos COM tales como _bstr_t para contener valores alfanuméricos.

    En la versión de la Tienda Windows de la aplicación, usamos std::wstring, el tipo de cadena de C++ estándar, para contener valores alfanuméricos. Por ejemplo, en el método TripOptimizerImpl::OptimizeTripAsync, convertimos los parámetros Windows::Foundation::Collections::IVector<T> y Platform::String en std::vector y std::wstring porque estas variables no se pasan a un componente de Windows en tiempo de ejecución.

    // 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;
    

    Cuando usas esta convención, puedes distinguir con más claridad qué variables se utilizan con Windows en tiempo de ejecución. Los tipos de cadenas y colecciones de Windows en tiempo de ejecución (como Windows::Foundation::Collections::IMap<K, V> y Windows::Foundation::Collections::IVector<T>) son útiles cuando te comunicas periódicamente entre Windows en tiempo de ejecución y el código porque reduce el número de conversiones de tipo de cadena que debe realizar la aplicación. De lo contrario, considera si debes utilizar tipos de colección de C++ estándar como std::map y std::vector.

    Los detalles de implementación del control se describen con más detalle en la sección Flujo de trabajo de componentes.

  • Usa las interfaces Windows::Foundation::IAsyncAction, Windows::Foundation::IAsyncActionWithProgress<TProgress>, Windows::Foundation::IAsyncOperation<TResult> o Windows::Foundation::IAsyncOperationWithProgress<TResult, TProgress> para ayudar a definir métodos asincrónicos. La función concurrency::create_async es la manera recomendada de crear estos objetos a partir de una aplicación o un componente de la Tienda Windows de C++.

  • Utiliza la mayor cantidad posible de código existente. Pudimos migrar los detalles de implementación, como el algoritmo de optimización basado en colonias de hormigas, con pocas o ninguna modificación de código. Sin embargo, como las aplicaciones de la Tienda Windows pueden usar un subconjunto de API de Win32 y COM, tuvimos que emplear otros mecanismos para algunas partes del componente. Por ejemplo, la versión de ActiveX del control utiliza IXMLHTTPRequest para comunicarse con los servidores HTTP. En el componente de C++, usamos IXMLHTTPRequest2, que es la manera recomendada de comunicarse con servidores HTTP en una aplicación de la Tienda Windows. Para procesar la respuesta de XML de Mapas de Bing, el control ActiveX utiliza XmlLite. En el componente de Tienda Windows, utilizamos la clase XmlDocument de Windows en tiempo de ejecución porque es fácil de usar y porque deseamos mostrar cómo puedes actualizar código COM existente para utilizar los tipos de Windows en tiempo de ejecución. Sin embargo, si tienes código Win32 o COM existente disponible en una aplicación de la Tienda Windows, puedes seguir usándolo.

    Para obtener más información sobre cómo utilizar Win32 y COM en una aplicación de Tienda Windows, consulta Win32 y COM para aplicaciones de la Tienda Windows.

    Nota importanteImportante

    Si usas Win32 y COM en tu aplicación de la Tienda Windows, puede ejecutarse en tu entorno de desarrollo, pero es posible que no se apruebe para la distribución desde la Tienda Windows.Por consiguiente, recomendamos que ejecutes el comprobador de aplicaciones con frecuencia para garantizar que tu aplicación supere la verificación.Para obtener más información, consulta Preparar tu aplicaciones para la Tienda Windows y Cómo: Instalar, validar y cargar el paquete.

  • Los proyectos deVisual C++ usan ahora pch.h y pch.cpp para contener la información de encabezado precompilado. Migra las instrucciones pertinentes de #include de stdafx.h a pch.h.

[Principio]

Puntos clave de migración de interoperabilidad

En la versión de la aplicación de la Tienda Windows de Optimizador de recorridos de Mapas de Bing, pudimos utilizar la mayor parte del código de JavaScript de la versión de ActiveX. La diferencia principal consiste en cómo el código HTML y de JavaScript hacen referencia al componente de C++.

La versión de ActiveX utiliza la etiqueta object HTML para hacer referencia al componente de C++.

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

En consecuencia, la versión de ActiveX usa el valor de id, “OptimizerControl”, para llamar a los métodos COptimizerControl.

La versión de la aplicación de la Tienda Windows de Optimizador de recorridos de Mapas de Bing establece una referencia de proyecto y utiliza una variable global en lugar de utilizar la etiqueta de object. El sistema del proyecto realiza estos pasos que son necesarios para que la aplicación JavaScript busque y cargue el componente de C++. El artículo Crear componentes de Windows en tiempo de ejecución en C++ explica con más detalle cómo se instalan las referencias del proyecto.

La versión de ActiveX usa la sintaxis :: para controlar eventos.

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

La versión de la aplicación de la Tienda Windows usa procesamiento asincrónico y compromisos para reaccionar a las respuestas del componente de C++. Este proceso se explica en la sección Recibir datos del componente de C++.

[Principio]