Partager via


Bien démarrer avec C++/WinRT

Important

Pour plus d’informations sur la configuration de Visual Studio pour le développement C++/WinRT, notamment l’installation et l’utilisation de l’extension Visual Studio C++/WinRT (VSIX) et du package NuGet (qui fournissent ensemble un modèle de projet et une prise en charge de build), consultez prise en charge de Visual Studio pour C++/WinRT.

Pour vous aider à utiliser C++/WinRT, cette rubrique décrit un exemple de code simple basé sur un nouveau projet d’application console Windows (C++/WinRT). Ce sujet montre également comment ajouter la prise en charge de C++/WinRT à un projet d’application de bureau Windows.

Remarque

Bien que nous vous recommandons de développer avec les dernières versions de Visual Studio et du Kit de développement logiciel (SDK) Windows, si vous utilisez Visual Studio 2017 (version 15.8.0 ou ultérieure) et ciblez le SDK Windows version 10.0.17134.0 (Windows 10, version 1803), un projet C++/WinRT nouvellement créé peut échouer avec l’erreur « erreur C3861 : « from_abi » : identificateur introuvable » et avec d’autres erreurs provenant de base.h. La solution consiste à cibler une version ultérieure (plus conforme) du Kit de développement logiciel (SDK) Windows, ou à définir la propriété de projet C/C++>mode de conformité du langage>: aucun (également, si /permissive- apparaît dans la propriété du projet C/C++>Langage>ligne de commande sous options supplémentaires, puis supprimez-le).

Démarrage rapide C++/WinRT

Créez un nouveau projet d'application console Windows (C++/WinRT).

Modifiez pch.h et main.cpp pour ressembler à ceci.

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

Prenons l’exemple de code court ci-dessus par morceau, et expliquer ce qui se passe dans chaque partie.

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

Avec les paramètres de projet par défaut, les en-têtes inclus proviennent du Kit de développement logiciel (SDK) Windows, à l’intérieur du dossier %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio inclut ce chemin dans sa macro IncludePath . Toutefois, il n’existe aucune dépendance stricte sur le Kit de développement logiciel (SDK) Windows, car votre projet (via l’outil cppwinrt.exe ) génère ces mêmes en-têtes dans le dossier $(GeneratedFilesDir) de votre projet. Ils seront chargés à partir de ce dossier s’ils ne sont pas trouvés ailleurs ou si vous modifiez les paramètres de votre projet.

Les en-têtes contiennent des API Windows projetées en C++/WinRT. En d'autres termes, pour chaque type Windows, C++/WinRT définit un équivalent adapté à C++ (appelé type projeté). Un type projeté a le même nom complet que le type Windows, mais il est placé dans l’espace de noms winrt C++. Le fait de placer ces éléments dans votre en-tête précompilé réduit les temps de compilation incrémentielle.

Important

Chaque fois que vous souhaitez utiliser un type à partir d’espaces de noms Windows, vous devez #include le fichier d’en-tête d’espace de noms Windows C++/WinRT correspondant, comme indiqué ci-dessus. Le en-tête correspondant est celui portant exactement le même nom que l'espace de noms du type. Par exemple, pour utiliser la projection C++/WinRT pour la classe runtime Windows::Foundation::Collections::PropertySet , incluez l’en-tête winrt/Windows.Foundation.Collections.h.

Il est courant qu’un en-tête de projection C++/WinRT inclut automatiquement les fichiers d’en-tête des espaces de noms associés. Par exemple, winrt/Windows.Foundation.Collections.h inclut winrt/Windows.Foundation.h. Mais vous ne devez pas vous appuyer sur ce comportement, car il s’agit d’un détail d’implémentation qui change au fil du temps. Vous devez inclure explicitement tous les en-têtes dont vous avez besoin.

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

Les directives using namespace sont facultatives, mais pratiques. Le modèle indiqué ci-dessus pour ces directives (autorisant la recherche de noms non qualifiée pour tout ce qui se trouve dans l’espace de noms winrt ) convient lorsque vous commencez un nouveau projet et que C++/WinRT est la seule projection de langage que vous utilisez à l’intérieur de ce projet. Si, d’autre part, vous mélangez du code C++/WinRT à C++/CX et/ou du code ABI (SDK Application Binary Interface) (à partir duquel vous effectuez le portage, ou interopération avec l'un ou l'autre de ces modèles), puis consultez les rubriques Interop entre C++/WinRT et C++/CX, Passer à C++/WinRT à partir de C++/CX, et Interop entre le ABI et C++/WinRT.

winrt::init_apartment();

L’appel à winrt ::init_apartment initialise le thread dans Windows Runtime ; par défaut, dans un appartement multithread. L’appel initialise également COM.

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

Allouez sur la pile deux objets : l'un représente l'uri du blog Windows et l'autre un client de syndication. Nous construisons l’URI avec un littéral de chaîne large simple (consultez gestion des chaînes en C++/WinRT pour plus de façons d’utiliser des chaînes).

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

SyndicationClient ::RetrieveFeedAsync est un exemple de fonction Windows Runtime asynchrone. L’exemple de code reçoit un objet d’opération asynchrone de RetrieveFeedAsync, et il appelle get sur cet objet pour bloquer le fil d'exécution appelant et attendre le résultat (qui est un flux de syndication, dans ce cas). Pour plus d’informations sur la concurrence et pour les techniques non bloquantes, consultez Concurrency et opérations asynchrones avec C++/WinRT.

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

SyndicationFeed.Items est une plage définie par les itérateurs retournés par les fonction de début et fonction de fin (ou leurs variantes constantes, inverses, et constantes inverses). Pour cette raison, vous pouvez énumérer Éléments avec une instruction for basée sur une plage ou avec la fonction template std::for_each. Chaque fois que vous effectuez une itération sur une collection Windows Runtime comme celle-ci, vous devez #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;

Obtient le texte du titre du flux, sous la forme d’un objet winrt::hstring (plus d’informations dans Gestion des chaînes en C++/WinRT). Le de hstring est ensuite généré via la fonction c_str, qui reflète le modèle utilisé avec les chaînes de bibliothèque standard C++.

Comme vous pouvez le voir, C++/WinRT encourage les expressions C++ modernes et de type classe, telles que syndicationItem.Title().Text(). Il s’agit d’un style de programmation différent et plus propre de la programmation COM traditionnelle. Vous n’avez pas besoin d’initialiser directement COM, ni d’utiliser des pointeurs COM.

Vous n’avez pas non plus besoin de gérer les codes de retour HRESULT. C++/WinRT convertit les hrESULT d’erreur en exceptions telles que winrt ::hresult-error pour un style de programmation naturel et moderne. Pour plus d’informations sur la gestion des erreurs et les exemples de code, consultez Gestion des erreurs avec C++/WinRT.

Modifier un projet d’application Windows Desktop pour ajouter la prise en charge de C++/WinRT

Certains projets de bureau (par exemple, les modèles WinUI 3 dans Visual Studio) ont la prise en charge C++/WinRT intégrée.

Toutefois, cette section vous montre comment ajouter la prise en charge de C++/WinRT à n’importe quel projet d’application Windows Desktop que vous avez peut-être. Si vous n’avez pas de projet d’application Windows Desktop existant, vous pouvez suivre ces étapes en créant d’abord un projet d’application Windows Desktop. Par exemple, ouvrez Visual Studio et créez un projet d'application Windows Desktop Visual C++>.

Vous pouvez éventuellement installer l’extension Visual Studio C++/WinRT (VSIX) et le package NuGet. Pour plus d’informations, consultez prise en charge de Visual Studio pour C++/WinRT.

Définir les propriétés d’un projet

Accédez à la propriété de projet Version générale> duKit de développement logiciel (SDK) Windows, puis sélectionnez Toutes les configurations et toutes les plateformes. Vérifiez que version du Kit de développement logiciel (SDK) Windows version est définie sur 10.0.17134.0 (Windows 10, version 1803) ou ultérieure.

Vérifiez que vous n’êtes pas affecté par Pourquoi mon nouveau projet ne sera-t-il pas compilé ?.

Étant donné que C++/WinRT utilise des fonctionnalités de la norme C++17, définissez la propriété de projet C/C++>Language>Standard du langage C++ sur ISO C++17 Standard (/std:c++17).

En-tête précompilé

Le modèle de projet par défaut crée un en-tête précompilé pour vous, nommé soit framework.h, soit stdafx.h. Renommez-le en pch.h. Si vous avez un stdafx.cpp fichier, renommez-le pch.cpp. Définissez la propriété de projet C/C++>en-têtes précompilés> d’en-tête précompilé sur (/Yc) et fichier d’en-tête précompilé sur pch.h.

Recherchez et remplacez toutes les #include "framework.h" (ou #include "stdafx.h") par #include "pch.h".

Dans pch.h, inclure winrt/base.h.

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

Connexion

La projection du langage C++/WinRT dépend de certaines fonctions Windows Runtime autonomes (non membres) et de points d’entrée qui nécessitent une liaison avec la bibliothèque WindowsApp.lib . Cette section décrit trois façons de satisfaire l’éditeur de liens.

La première option consiste à ajouter à votre projet Visual Studio toutes les propriétés et cibles MSBuild C++/WinRT. Pour ce faire, installez dans votre projet le package NuGet Microsoft.Windows.CppWinRT. Ouvrez le projet dans Visual Studio, cliquez sur Projet>Gérer les packages NuGet...>Parcourir, tapez ou collez Microsoft.Windows.CppWinRT dans la zone de recherche, sélectionnez l’élément dans les résultats de recherche, puis cliquez sur Installer pour installer le package pour ce projet.

Vous pouvez également utiliser les paramètres de lien de projet pour lier WindowsApp.libexplicitement . Vous pouvez également le faire dans le code source (par pch.hexemple) comme suit.

#pragma comment(lib, "windowsapp")

Vous pouvez maintenant compiler et lier votre projet, puis y ajouter du code C++/WinRT (par exemple, du code similaire à celui présenté dans la section Une prise en main rapide de C++/WinRT ci-dessus).

Les trois principaux scénarios pour C++/WinRT

À mesure que vous utilisez et familiarisez-vous avec C++/WinRT, et que vous parcourez le reste de la documentation ici, vous remarquerez probablement qu’il existe trois scénarios principaux, comme décrit dans les sections suivantes.

Consommation d’API et de types Windows

En d’autres termes, en utilisantavec , ou en appelant des API avec . Par exemple, effectuer des appels d’API pour communiquer à l’aide de Bluetooth ; pour diffuser et présenter une vidéo ; pour s’intégrer à l’interpréteur de commandes Windows ; et ainsi de suite. C++/WinRT prend entièrement en charge cette catégorie de scénario. Pour plus d’informations, consultez Consommer des API avec C++/WinRT.

Création d’API et de types Windows

En d'autres termes, produire des API et des types. Par exemple, produire les types d’API décrits dans la section ci-dessus ; ou les API graphiques ; les API de stockage et de système de fichiers ; les API de mise en réseau, et ainsi de suite. Pour plus d’informations, consultez Créer des API avec C++/WinRT.

La création d’API avec C++/WinRT est un peu plus impliquée que de les consommer, car vous devez utiliser IDL pour définir la forme de l’API avant de pouvoir l’implémenter. Il existe une procédure pas à pas pour ce faire dans les contrôles XAML : en la liant à une propriété C++/WinRT.

Applications basées sur XAML

Ce scénario concerne la création d’applications et de contrôles sur l’infrastructure d’interface utilisateur XAML. L’utilisation d’une application XAML équivaut à une combinaison de consommation et de création. Mais étant donné que XAML est l’infrastructure d’interface utilisateur dominante sur Windows aujourd’hui, et son influence sur Windows Runtime est proportionnelle à cela, elle mérite sa propre catégorie de scénario.

Sachez que XAML fonctionne le mieux avec les langages de programmation qui offrent une réflexion. En C++/WinRT, vous devez parfois effectuer un peu de travail supplémentaire pour interagir avec l’infrastructure XAML. Tous ces cas sont abordés dans la documentation. De bons points de départ sont les contrôles XAML , liez à une propriété C++/WinRT et les contrôles XAML personnalisés avec modèles avec C++/WinRT.

Exemples d’applications écrites en C++/WinRT

Voir Où puis-je trouver des exemples d’applications C++/WinRT ?.

API importantes