Introducción a C++/WinRTGet started with C++/WinRT

Para ponerte al día con el uso de C++/WinRT, este tema te guía mediante un ejemplo de código sencillo basado en un nuevo proyecto de aplicación de consola Windows (C++/WinRT) .To get you up to speed with using C++/WinRT, this topic walks through a simple code example based on a new Windows Console Application (C++/WinRT) project. En este tema también se muestra cómo agregar compatibilidad de C++/WinRT a un proyecto de aplicación de escritorio de Windows.This topic also shows how to add C++/WinRT support to a Windows Desktop application project.

Nota

Aunque recomendamos que desarrolles con las versiones más recientes de Visual Studio y del SDK de Windows, si usas Visual Studio 2017 (versión 15.8.0 o superior) y te diriges al SDK de Windows versión 10.0.17134.0 (Windows 10, versión 1803), un proyecto recién creado de C++/WinRT puede generar un error al compilarse con el "error C3861: 'from_abi': no se encontró el identificador" y otros errores que se originan en base.h.While we recommend that you develop with the latest versions of Visual Studio and the Windows SDK, if you're using Visual Studio 2017 (version 15.8.0 or higher), and targeting the Windows SDK version 10.0.17134.0 (Windows 10, version 1803), then a newly created C++/WinRT project may fail to compile with the error "error C3861: 'from_abi': identifier not found", and with other errors originating in base.h. La solución consiste en dirigirte a una versión posterior (más compatible) del SDK de Windows o establecer la propiedad del proyecto C/C++ > Lenguaje > Modo de conformidad: No (además, si /permissive- aparece en la propiedad del proyecto C/C++ > Lenguaje > Línea de comandos en Opciones adicionales, elimínalo).The solution is to either target a later (more conformant) version of the Windows SDK, or set project property C/C++ > Language > Conformance mode: No (also, if /permissive- appears in project property C/C++ > Language > Command Line under Additional Options, then delete it).

Inicio rápido de C++/WinRTA C++/WinRT quick-start

Nota

Para más información sobre cómo instalar Visual Studio para la implementación de C++/WinRT —incluida la instalación y el uso de la Extensión de Visual Studio (VSIX) para C++/WinRT y el paquete NuGet (que juntos proporcionan la plantilla de proyecto y compatibilidad de la compilación)—, consulta Compatibilidad de Visual Studio para C++/WinRT.For info about setting up Visual Studio for C++/WinRT development—including installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support)—see Visual Studio support for C++/WinRT.

Crea un nuevo proyecto de la aplicación de consola Windows (C++/WinRT) .Create a new Windows Console Application (C++/WinRT) project.

Edita pch.h y main.cpp para que tengan este aspecto.Edit pch.h and main.cpp to look like this.

// 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;
    SyndicationFeed syndicationFeed = syndicationClient.RetrieveFeedAsync(rssFeedUri).get();
    for (const SyndicationItem syndicationItem : syndicationFeed.Items())
    {
        winrt::hstring titleAsHstring = syndicationItem.Title().Text();
        std::wcout << titleAsHstring.c_str() << std::endl;
    }
}

Tomemos el ejemplo de código corto anterior parte por parte; vamos a explicar qué pasa en cada parte.Let's take the short code example above piece by piece, and explain what's going on in each part.

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

Con la configuración del proyecto predeterminada, los encabezados incluidos proceden del SDK de Windows, dentro de la carpeta %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt.With the default project settings, the included headers come from the Windows SDK, inside the folder%WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio incluye dicha ruta de acceso en su macro IncludePath.Visual Studio includes that path in its IncludePath macro. Pero no hay ninguna dependencia estricta en el SDK de Windows porque el proyecto (a través de la herramienta cppwinrt.exe) genera los mismos encabezados en la carpeta $(GeneratedFilesDir) del proyecto.But there's no strict dependency on the Windows SDK, because your project (via the cppwinrt.exe tool) generates those same headers into your project's $(GeneratedFilesDir) folder. Se cargarán desde esa carpeta si no se encuentran en otra parte o si cambias la configuración del proyecto.They'll be loaded from that folder if they can't be found elsewhere, or if you change your project settings.

Los encabezados contienen las API de Windows proyectadas en C++/WinRT.The headers contain Windows APIs projected into C++/WinRT. En otras palabras, para cada tipo de Windows, C++/WinRT define un equivalente de C++ descriptivo (denominado el tipo proyectado).In other words, for each Windows type, C++/WinRT defines a C++-friendly equivalent (called the projected type). Un tipo proyectado tiene el mismo nombre completo que el tipo de Windows, pero se coloca en el espacio de nombres winrt de C++.A projected type has the same fully-qualified name as the Windows type, but it's placed in the C++ winrt namespace. La colocación de estas inclusiones en tu encabezado precompilado reduce el tiempo de compilación incremental.Putting these includes in your precompiled header reduces incremental build times.

Importante

Siempre que quiera usar un tipo de un espacio de nombres de Windows, debe usar #include para el archivo de encabezado de espacio de nombres de Windows C++/WinRT correspondiente, tal como se ha mostrado anteriormente.Whenever you want to use a type from a Windows namespaces, you must #include the corresponding C++/WinRT Windows namespace header file, as shown above. El encabezado correspondiente es el que tiene el mismo nombre que el espacio de nombres del tipo.The corresponding header is the one with the same name as the type's namespace. Por ejemplo, para usar la proyección de C++ o WinRT para la clase en tiempo de ejecución Windows::Foundation::Collections::PropertySet, incluya el encabezado winrt/Windows.Foundation.Collections.h.For example, to use the C++/WinRT projection for the Windows::Foundation::Collections::PropertySet runtime class, include the winrt/Windows.Foundation.Collections.h header.

Es habitual que un encabezado de proyección de C++/WinRT incluya automáticamente su archivo de encabezado de espacio de nombres primario.It's usual for a C++/WinRT projection header to automatically include its parent namespace header file. Por lo tanto, por ejemplo, winrt/Windows.Foundation.Collections.h incluye winrt/Windows.Foundation.h.So, for example, winrt/Windows.Foundation.Collections.h includes winrt/Windows.Foundation.h. Pero no debe confiar en este comportamiento, ya que es un detalle de implementación que cambia con el tiempo.But you shouldn't rely on this behavior, since it's an implementation detail that changes over time. Debe incluir explícitamente los encabezados que necesite.You must explicitly include any headers that you need.

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

Las directivas using namespace son opcionales, pero recomendables.The using namespace directives are optional, but convenient. El patrón mostrado anteriormente para dichas directivas (que permite la búsqueda de nombres no completos en el espacio de nombres winrt) es adecuado cuando comienzas un proyecto nuevo y C++/WinRT es la única proyección de lenguaje que usas dentro de ese proyecto.The pattern shown above for such directives (allowing unqualified name lookup for anything in the winrt namespace) is suitable for when you're beginning a new project and C++/WinRT is the only language projection you're using inside of that project. Si, por otro lado, combinas código de C++/WinRT con C++/CX o código de interfaz binaria de aplicación (ABI) del SDK (desde el que vas a migrar, o con el que vas a interoperar, uno o ambos de esos modelos), consulta los temas Interoperabilidad entre C++/WinRT y C++/CX, Mover a C++/WinRT desde C++/CX e Interoperabilidad entre C++/WinRT y la ABI.If, on the other hand, you're mixing C++/WinRT code with C++/CX and/or SDK application binary interface (ABI) code (you're either porting from, or interoperating with, one or both of those models), then see the topics Interop between C++/WinRT and C++/CX, Move to C++/WinRT from C++/CX, and Interop between C++/WinRT and the ABI.

winrt::init_apartment();

La llamada a winrt::init_apartment inicializa el subproceso en Windows Runtime; de manera predeterminada, en un contenedor multiproceso.The call to winrt::init_apartment initializes the thread in the Windows Runtime; by default, in a multithreaded apartment. La llamada también inicializa COM.The call also initializes COM.

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

Asigna a la pila dos objetos: representan el URI del blog de Windows y un cliente de distribución.Stack-allocate two objects: they represent the uri of the Windows blog, and a syndication client. Construimos el URI con un literal de cadena ancho sencillo (consulta Control de cadenas en C++/WinRT para ver más maneras con las que puedes trabajar con cadenas).We construct the uri with a simple wide string literal (see String handling in C++/WinRT for more ways you can work with strings).

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

SyndicationClient::RetrieveFeedAsync es un ejemplo de una función asincrónica de Windows Runtime.SyndicationClient::RetrieveFeedAsync is an example of an asynchronous Windows Runtime function. El siguiente ejemplo de código recibe un objeto de operación asincrónica desde RetrieveFeedAsync y llama a get en dicho objeto para bloquear el subproceso de llamada y esperar el resultado (que es una fuente de distribución en este caso).The code example receives an asynchronous operation object from RetrieveFeedAsync, and it calls get on that object to block the calling thread and wait for the result (which is a syndication feed, in this case). Para más información sobre la simultaneidad y las técnicas de no bloqueo, consulta Operaciones simultáneas y asincrónicas con C++/WinRT.For more about concurrency, and for non-blocking techniques, see Concurrency and asynchronous operations with C++/WinRT.

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

SyndicationFeed.Items es un intervalo definido por los iteradores devueltos a partir de las funciones begin y end (o sus variantes constantes, inversas y constante-inversas).SyndicationFeed.Items is a range, defined by the iterators returned from begin and end functions (or their constant, reverse, and constant-reverse variants). Por este motivo, puedes enumerar Items con una instrucción for basada en intervalo o con la función de plantilla std::for_each.Because of this, you can enumerate Items with either a range-based for statement, or with the std::for_each template function. Cada vez que recorras en iteración una colección de Windows Runtime similar a la siguiente, tendrás que aplicar #include <winrt/Windows.Foundation.Collections.h>.Whenever you iterate over a Windows Runtime collection like this, you'll need to #include <winrt/Windows.Foundation.Collections.h>.

winrt::hstring titleAsHstring = syndicationItem.Title().Text();
std::wcout << titleAsHstring.c_str() << std::endl;

Obtiene el texto del título de la fuente, como objeto winrt::hstring (consulta más detalles en Control de cadenas en C++/WinRT).Gets the feed's title text, as a winrt::hstring object (more details in String handling in C++/WinRT). Entonces se genera hstring, mediante la función c_str, que refleja el patrón utilizado con cadenas de la biblioteca estándar de C++.The hstring is then output, via the c_str function, which reflects the pattern used with C++ Standard Library strings.

Como puedes ver, C++/WinRT fomenta expresiones de C++ modernas y de tipo clase, como syndicationItem.Title().Text().As you can see, C++/WinRT encourages modern, and class-like, C++ expressions such as syndicationItem.Title().Text(). Es un estilo de programación diferente y más limpio que la tradicional programación COM.This is a different, and cleaner, programming style from traditional COM programming. No tienes que inicializar COM directamente, ni trabajar con punteros COM.You don't need to directly initialize COM, nor work with COM pointers.

Tampoco necesitas controlar códigos de devolución HRESULT.Nor do you need to handle HRESULT return codes. C++/WinRT convierte los errores HRESULT en excepciones como winrt::hresult-error para lograr un estilo de programación natural y moderno.C++/WinRT converts error HRESULTs to exceptions such as winrt::hresult-error for a natural and modern programming style. Para más información acerca del control de errores y ejemplos de código, consulta Gestión de errores con C++/WinRT.For more info about error-handling, and code examples, see Error handling with C++/WinRT.

Modificación de un proyecto de aplicación de escritorio de Windows para agregar compatibilidad de C++/WinRTModify a Windows Desktop application project to add C++/WinRT support

En esta sección se muestra cómo agregar compatibilidad de C++/WinRT a un proyecto de aplicación de escritorio de Windows que puedas tener.This section shows you how you can add C++/WinRT support to a Windows Desktop application project that you might have. Si no tienes ningún proyecto de aplicación de escritorio de Windows, puedes seguir estos pasos para crear uno.If you don't have an existing Windows Desktop application project, then you can follow along with these steps by first creating one. Por ejemplo, abre Visual Studio y crea un proyecto de Visual C++ > Escritorio de Windows > Aplicación de escritorio de Windows.For example, open Visual Studio and create a Visual C++ > Windows Desktop > Windows Desktop Application project.

También puedes instalar opcionalmente la Extensión de Visual Studio (VSIX) para C++/WinRT y el paquete NuGet.You can optionally install the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package. Para más información, consulta Compatibilidad de Visual Studio para C++/WinRT.For details, see Visual Studio support for C++/WinRT.

Configuración de propiedades del proyectoSet project properties

En la propiedad del proyecto General > Versión del SDK de Windows, selecciona Todas las configuraciones y Todas las plataformas.Go to project property General > Windows SDK Version, and select All Configurations and All Platforms. Asegúrate de que Versión del SDK de Windows esté establecido en 10.0.17134.0 (Windows 10, versión 1803) o superior.Ensure that Windows SDK Version is set to 10.0.17134.0 (Windows 10, version 1803) or greater.

Confirma que no te afecte ¿Por qué no se compilará mi nuevo proyecto?.Confirm that you're not affected by Why won't my new project compile?.

Dado que C++/WinRT usa características del estándar C++17, establece la propiedad del proyecto C/C++ > Lenguaje > Estándar de lenguaje C++ en Estándar ISO C++17 (/std:c++17) en Visual Studio.Because C++/WinRT uses features from the C++17 standard, set project property C/C++ > Language > C++ Language Standard to ISO C++17 Standard (/std:c++17).

Encabezado precompiladoThe precompiled header

La plantilla de proyecto predeterminada crea automáticamente un encabezado precompilado, denominado framework.h o stdafx.h.The default project template creates a precompiled header for you, named either framework.h, or stdafx.h. Cámbiale el nombre a pch.h.Rename that to pch.h. Si tienes un archivo stdafx.cpp, cámbiale el nombre a pch.cpp.If you have a stdafx.cpp file, then rename that to pch.cpp. Establece la propiedad del proyecto C/C++ > Encabezados precompilados > Encabezado precompilado en Crear (/Yc) y Archivo de encabezado precompilado en pch.h.Set project property C/C++ > Precompiled Headers > Precompiled Header to Create (/Yc), and Precompiled Header File to pch.h.

Busca y reemplaza todos los #include "framework.h" (o #include "stdafx.h") por #include "pch.h".Find and replace all #include "framework.h" (or #include "stdafx.h") with #include "pch.h".

En pch.h, incluye winrt/base.h.In pch.h, include winrt/base.h.

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

VinculaciónLinking

La proyección de lenguaje de C++/WinRT depende de algunas funciones de Windows Runtime y puntos de entrada libres (no miembros), que requieren la vinculación a la biblioteca paraguas WindowsApp.lib.The C++/WinRT language projection depends on certain Windows Runtime free (non-member) functions, and entry points, that require linking to the WindowsApp.lib umbrella library. En esta sección se describen tres maneras de satisfacer al enlazador.This section describes three ways of satisfying the linker.

La primera opción consiste en agregar al proyecto de Visual Studio todas las propiedades y los destinos de MSBuild de C++WinRT.The first option is to add to your Visual Studio project all of the C++/WinRT MSBuild properties and targets. Para ello, instala el paquete NuGet Microsoft.Windows.CppWinRT en el proyecto.To do this, install the Microsoft.Windows.CppWinRT NuGet package into your project. Abre el proyecto en Visual Studio, haz clic en Proyecto > Administrar paquetes NuGet... > Busca, escribe o pega Microsoft.Windows.CppWinRT en el cuadro de búsqueda, selecciona el elemento en los resultados de la búsqueda y haz clic en Instalar para instalar el paquete de ese proyecto.Open the project in Visual Studio, click Project > Manage NuGet Packages... > Browse, type or paste Microsoft.Windows.CppWinRT in the search box, select the item in search results, and then click Install to install the package for that project.

También puedes usar la configuración de vínculo del proyecto para vincular explícitamente WindowsApp.lib.You can also use project link settings to explicitly link WindowsApp.lib. O bien, puedes hacerlo en código fuente (en pch.h, por ejemplo), como en este ejemplo.Or, you can do it in source code (in pch.h, for example) like this.

#pragma comment(lib, "windowsapp")

Ya puedes 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 C++/WinRT anterior).You can now compile and link, and add C++/WinRT code to your project (for example, code similar to that shown in the A C++/WinRT quick-start section, above).

Los tres escenarios principales de C++/WinRTThe three main scenarios for C++/WinRT

A medida que uses C++/WinRT y te familiarices con él, y consultes el resto de la documentación que se incluye aquí, es probable que observes que hay tres escenarios principales, como se describe en las secciones siguientes.As you use and become familiar with C++/WinRT, and work through the rest of the documentation here, you'll likely notice that there are three main scenarios, as described in the following sections.

Consumo de tipos y API de Windows RuntimeConsuming Windows Runtime APIs and types

En otras palabras, usar o llamar a las API.In other words, using, or calling APIs. Por ejemplo, realizar llamadas API para comunicarse mediante Bluetooth, para transmitir y presentar vídeo, para integrar con el shell de Windows, etc.For example, making API calls to communicate using Bluetooth; to stream and present video; to integrate with the Windows shell; and so on. C++/WinRT es totalmente compatible con esta categoría de escenario.C++/WinRT fully and uncompromisingly supports this category of scenario. Para más información, consulta Consumir API con C++/WinRT.For more info, see Consume APIs with C++/WinRT.

Creación de tipos y API de Windows RuntimeAuthoring Windows Runtime APIs and types

En otras palabras, producir tipos y API.In other words, producing APIs and types. Por ejemplo, producir los tipos de API que se describen en la sección anterior, o bien las API de gráficos, las API de almacenamiento y del sistema de archivos, las API de redes, etc.For example, producing the kinds of APIs described in the section above; or the graphics APIs; the storage and file system APIs; the networking APIs, and so on. Para obtener más información, consulta Crear API con C++/WinRT.For more info, see Author APIs with C++/WinRT.

Crear API con C++/WinRT es un poco más complicado que consumirlas, porque debes usar IDL para definir la forma de la API antes de poder implementarla.Authoring APIs with C++/WinRT is a little more involved than consuming them, because you must use IDL to define the shape of the API before you can implement it. Hay un tutorial para hacerlo en Controles de XAML; enlazar a una propiedad de C++/WinRT.There's a walkthrough of doing that in XAML controls; bind to a C++/WinRT property.

Aplicaciones XAMLXAML applications

En este escenario se trata la compilación de aplicaciones y controles en el marco de trabajo de la interfaz de usuario de XAML.This scenario is about building applications and controls on the XAML UI framework. Trabajar en una aplicación XAML equivale a una combinación de consumo y creación.Working in a XAML application amounts to a combination of consuming and authoring. Pero, dado que XAML es el marco de trabajo de la interfaz de usuario dominante en Windows hoy en día y su influencia en Windows Runtime es proporcional a eso, merece su propia categoría de escenario.But since XAML is the dominant UI framework on Windows today, and its influence over the Windows Runtime is proportionate to that, it deserves its own category of scenario.

Ten en cuenta que XAML funciona mejor con los lenguajes de programación que ofrecen reflexión.Be aware that XAML works best with programming languages that offer reflection. En C++/WinRT, a veces tienes que esforzarte un poco más para interoperar con el marco XAML.In C++/WinRT, you sometimes have to do a little extra work in order to interoperate with the XAML framework. Todos estos casos se describen en la documentación.All of those cases are covered in the documentation. Los mejores artículos para empezar son Controles de XAML; enlazar a una propiedad de C++/WinRT y Controles (basados en modelo) personalizados de XAML con C++/WinRT.Good places to start are XAML controls; bind to a C++/WinRT property and XAML custom (templated) controls with C++/WinRT.

Aplicaciones de ejemplo escritas en C++/WinRTSample apps written in C++/WinRT

Consulte ¿Dónde puedo encontrar aplicaciones de ejemplo de C++/WinRT?See Where can I find C++/WinRT sample apps?.

API importantesImportant APIs