Compartir a través de


Introducción a C++/WinRT

Importante

Para obtener información sobre cómo configurar Visual Studio para el desarrollo de C++/WinRT, incluida la instalación y el uso de la extensión de Visual Studio de C++/WinRT (VSIX) y el paquete NuGet (que proporcionan junto la plantilla de proyecto y la compatibilidad con la compilación), consulte compatibilidad de Visual Studio con C++/WinRT.

Para ponerle al corriente en el uso de C++/WinRT , este tema le guía a través de un sencillo ejemplo de código basado en un nuevo proyecto de aplicación de consola de Windows (C++/WinRT) . En este tema también se muestra cómo agregar compatibilidad con C++/WinRT a un proyecto de aplicación de escritorio de Windows.

Nota:

Aunque se recomienda desarrollar con las versiones más recientes de Visual Studio y Windows SDK, Si usa Visual Studio 2017 (versión 15.8.0 o posterior) y tiene como destino la versión 10.0.17134.0 de Windows SDK (Windows 10, versión 1803), es posible que un proyecto de C++/WinRT recién creado no se compile con el error "error C3861: "from_abi": identificador no encontrado", y con otros errores que se originan en base.h. La solución consiste en tener como destino una versión posterior (más conforme) del SDK de Windows o establecer la propiedad del proyecto C/C++>Lenguaje>modo de conformidad: No (también, si /permissive- aparece en la propiedad del proyecto C/C++>Lenguaje>línea de comandos en opciones adicionales, entonces, elimínelo).

Inicio rápido de C++/WinRT

Cree un nuevo proyecto de aplicación de consola de Windows (C++/WinRT).

Edite pch.h y main.cpp para que tenga este aspecto.

// pch.h
#pragma once
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>
#include <iostream>
// main.cpp
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

int main()
{
    winrt::init_apartment();

    Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
    SyndicationClient syndicationClient;
    syndicationClient.SetRequestHeader(L"User-Agent", L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
    SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
    for (const SyndicationItem syndicationItem : syndicationFeed.Items())
    {
        winrt::hstring titleAsHstring = syndicationItem.Title().Text();
        
        // A workaround to remove the trademark symbol from the title string, because it causes issues in this case.
        std::wstring titleAsStdWstring{ titleAsHstring.c_str() };
        titleAsStdWstring.erase(remove(titleAsStdWstring.begin(), titleAsStdWstring.end(), L'™'), titleAsStdWstring.end());
        titleAsHstring = titleAsStdWstring;

        std::wcout << titleAsHstring.c_str() << std::endl;
    }
}

Vamos a tomar el breve ejemplo de código anterior por fragmento y explicar lo que sucede en cada parte.

#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Syndication.h>

Con la configuración predeterminada del proyecto, los encabezados incluidos proceden de Windows SDK, dentro de la carpeta %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio incluye esa ruta de acceso en su macro IncludePath. Sin embargo, no hay ninguna dependencia estricta en Windows SDK, ya que el proyecto (a través de la herramienta cppwinrt.exe) genera esos mismos encabezados en la carpeta $(GeneratedFilesDir) del proyecto. Se cargarán desde esa carpeta si no se encuentran en otro lugar o si cambia la configuración del proyecto.

Los encabezados contienen las API de Windows proyectadas en C++/WinRT. En otras palabras, para cada tipo de Windows, C++/WinRT define un equivalente de C++ fácil de usar (denominado tipo proyectado ). Un tipo proyectado tiene el mismo nombre totalmente cualificado que el tipo de Windows, pero se coloca en el espacio de nombres de C++ winrt. Al colocar estos elementos en el encabezado precompilado, se reducen los tiempos de compilación incrementales.

Importante

Siempre que quieras usar un tipo de un espacio de nombres de Windows, debes #include el archivo de encabezado del espacio de nombres de Windows de C++/WinRT correspondiente, como se muestra anteriormente. El encabezado de correspondiente es el que tiene el mismo nombre que el espacio de nombres del tipo. Por ejemplo, para usar la proyección de C++/WinRT para la Windows::Foundation::Collections::PropertySet clase en tiempo de ejecución, incluya el encabezado winrt/Windows.Foundation.Collections.h.

Es habitual que un encabezado de proyección de C++/WinRT incluya automáticamente archivos de encabezado de espacio de nombres relacionados. Por ejemplo, winrt/Windows.Foundation.Collections.h incluye winrt/Windows.Foundation.h. Pero no debe basarse en este comportamiento, ya que es un detalle de implementación que cambia con el tiempo. Debe incluir explícitamente los encabezados que sean necesarios.

using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Web::Syndication;

Las directivas using namespace son opcionales, pero convenientes. El patrón mostrado anteriormente para estas directivas (lo que permite la búsqueda de nombres sin calificar para cualquier cosa en el winrt espacio de nombres) es adecuado para cuando se inicia un nuevo proyecto y C++/WinRT es la única proyección de lenguaje que se usa dentro de ese proyecto. Por otro lado, está mezclando código de C++/WinRT con código de la interfaz binaria de aplicaciones (ABI) de C++/CX o C++/ CX (desde el que se va a migrar, o interoperar con, uno o ambos modelos), a continuación, vea los temas Interoperabilidad entre C++/WinRT y C++/CX, Mover a C++/WinRT desde C++/CX, y interoperabilidad entre C++/WinRT y la abi.

winrt::init_apartment();

La llamada a winrt::init_apartment inicializa el subproceso en Windows Runtime; de forma predeterminada, en un apartamento multiproceso. La llamada también inicializa COM.

Uri rssFeedUri{ L"https://blogs.windows.com/feed" };
SyndicationClient syndicationClient;

Asignación de pila de dos objetos: representan el URI del blog de Windows y un cliente de distribución. Creamos el URI con un literal de cadena ancha simple (consulta control de cadenas en C++/WinRT para obtener más formas de trabajar con cadenas).

SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();

SyndicationClient::RetrieveFeedAsync es un ejemplo de una función asincrónica de Windows Runtime. El ejemplo de código recibe un objeto de operación asincrónica de RetrieveFeedAsyncy llama a get en ese objeto para bloquear el subproceso de llamada y esperar el resultado (que, en este caso, es un feed de sindicación). Para obtener más información sobre la simultaneidad y para las técnicas de no bloqueo, consulte operaciones de simultaneidad y asincrónicas con C++/WinRT.

for (const SyndicationItem syndicationItem : syndicationFeed.Items()) { ... }

SyndicationFeed.Items es un intervalo definido por los iteradores devueltos por las funciones inicio y fin (o sus variantes constantes, inversas y reverso-constantes). Debido a esto, puede enumerar Elementos con una declaración basada en intervalos for, o con la función de plantilla std::for_each. Siempre que iteras en una colección de Windows Runtime como esta, tendrás que #include <winrt/Windows.Foundation.Collections.h>.

winrt::hstring titleAsHstring = syndicationItem.Title().Text();

// Omitted: there's a little bit of extra work here to remove the trademark symbol from the title text.

std::wcout << titleAsHstring.c_str() << std::endl;

Obtiene el texto del título de la fuente, como un objeto winrt::hstring (más detalles en manejo de cadenas en C++/WinRT). El hstring se muestra luego mediante la función c_str, que refleja el patrón utilizado con las cadenas de la biblioteca estándar de C++.

Como puede ver, C++/WinRT fomenta expresiones modernas y similares a clases, C++ como syndicationItem.Title().Text(). Este es un estilo de programación diferente y más limpio de la programación COM tradicional. No es necesario inicializar COM directamente, ni trabajar con punteros COM.

Tampoco es necesario gestionar los códigos de retorno HRESULT. C++/WinRT convierte los HRESULTs de error en excepciones como winrt::hresult-error, ofreciendo un estilo de programación natural y moderno. Para obtener más información sobre el control de errores y ejemplos de código, consulta Control de errores con C++/WinRT.

Modificación de un proyecto de aplicación de escritorio de Windows para agregar compatibilidad con C++/WinRT

Algunos proyectos de escritorio (por ejemplo, las plantillas WinUI 3 en Visual Studio) tienen compatibilidad integrada con C++/WinRT.

Pero en esta sección se muestra cómo agregar compatibilidad con C++/WinRT a cualquier proyecto de aplicación de escritorio de Windows que pueda tener. Si no tiene un proyecto de aplicación de escritorio de Windows existente, puede seguir estos pasos mediante la primera creación de uno. Por ejemplo, abra Visual Studio y cree un proyecto Visual C++>Aplicación de Escritorio de Windows>.

Puede instalar de forma opcional la extensión de C++/WinRT para Visual Studio (VSIX) y el paquete NuGet. Para obtener más información, consulte compatibilidad de Visual Studio con C++/WinRT.

Configurar propiedades del proyecto

Diríjase a la propiedad del proyecto General>Versión de Windows SDKy seleccione Todas las configuraciones y Todas las plataformas. Asegúrese de que versión de Windows SDK está establecido en 10.0.17134.0 (Windows 10, versión 1803) o posterior.

Confirme que no se ve afectado por ¿Por qué no se compilará mi nuevo proyecto?.

Dado que C++/WinRT usa características del estándar de C++17, establezca la propiedad del proyecto C/C++>Lenguaje>Estándar de C++ a Estándar ISO C++17 (/std:c++17).

Encabezado precompilado

La plantilla de proyecto predeterminada crea un encabezado precompilado para usted, denominado framework.ho stdafx.h. Cambie el nombre a pch.h. Si tiene un archivo stdafx.cpp, cambie el nombre a pch.cpp. Establezca la propiedad del proyecto C/C++>Encabezados Precompilados>Encabezado Precompilado a Crear (/Yc), y Archivo de Encabezado Precompilado a pch.h.

Busque y reemplace todos los #include "framework.h" (o #include "stdafx.h") por #include "pch.h".

En pch.h, incluya winrt/base.h.

// pch.h
...
#include <winrt/base.h>

Vinculación

La proyección de lenguaje C++/WinRT depende de ciertas funciones libres (no miembro) de Windows Runtime y de puntos de entrada que requieren la vinculación con la biblioteca WindowsApp.lib. En esta sección se describen tres maneras de satisfacer el enlazador.

La primera opción es agregar al proyecto de Visual Studio todas las propiedades y destinos de MSBuild de C++/WinRT. Para ello, instale el paquete NuGet Microsoft.Windows.CppWinRT a tu proyecto. Abra el proyecto en Visual Studio, haga clic en Proyecto>Administrar paquetes NuGet...>Examinar, escriba o pegue Microsoft.Windows.CppWinRT en el cuadro de búsqueda, seleccione el elemento en los resultados de búsqueda y haga clic en Instalar para instalar el paquete para ese proyecto.

También puede usar la configuración de enlaces del proyecto para vincular explícitamente WindowsApp.lib. O bien, puede hacerlo en el código fuente (en pch.h, por ejemplo) como este.

#pragma comment(lib, "windowsapp")

Ahora puede compilar y vincular y agregar código de C++/WinRT al proyecto (por ejemplo, código similar al que se muestra en la sección inicio rápido de A C++/WinRT anterior).

Los tres escenarios principales para C++/WinRT

A medida que use y se familiarice con C++/WinRT, y trabaje con el resto de la documentación aquí, es probable que observe que hay tres escenarios principales, como se describe en las secciones siguientes.

Consumo de APIs y tipos de Windows

Es decir, medianteo llamando a las API de. Por ejemplo, realizar llamadas API para comunicarse mediante Bluetooth; para transmitir y presentar vídeo; para integrar con el shell de Windows; y así sucesivamente. C++/WinRT es totalmente compatible con esta categoría de escenario. Para obtener más información, consulta Utilizar API con C++/WinRT.

Creación de API y tipos de Windows

Es decir, producir API y tipos. Por ejemplo, generar los tipos de API que se describen en la sección anterior; o las API de gráficos; las API de almacenamiento y sistema de archivos; las API de red, etc. Para obtener más información, consulta API de autor con C++/WinRT.

La creación de API con C++/WinRT es un poco más compleja que utilizarlas, ya que debe usar IDL para definir la forma de la API antes de poder implementarla. Hay una guía que explica cómo hacerlo en los controles XAML de , vincular a una propiedad de C++/WinRT.

Aplicaciones XAML

Este escenario consiste en crear aplicaciones y controles en el marco de interfaz de usuario XAML. Trabajar en una aplicación XAML equivale a una combinación de consumo y creación. Pero dado que XAML es el marco de interfaz de usuario dominante en Windows en la actualidad, y su influencia sobre Windows Runtime es proporcional a eso, merece su propia categoría de escenario.

Ten en cuenta que XAML funciona mejor con lenguajes de programación que ofrecen reflexión. En C++/WinRT, a veces tienes que hacer un poco de trabajo adicional para interoperar con el marco XAML. Todos esos casos se tratan en la documentación. Buenos lugares para empezar son los controles XAML ; vincular a una propiedad de C++/WinRT y controles personalizados XAML (con plantilla) con C++/WinRT.

Aplicaciones de ejemplo escritas en C++/WinRT

Consulte ¿Dónde puedo encontrar aplicaciones de ejemplo de C++/WinRT?.

API importantes