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 de 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 Visual Studio prise en charge de 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 (C++/WinRT) Windows. Cette rubrique montre également comment ajouter la prise en charge de C++/WinRT à un projet d’application de bureau Windows.

Note

Bien que nous vous recommandons de développer avec les dernières versions de Visual Studio et le SDK Windows, si vous utilisez Visual Studio 2017 (version 15.8.0 ou ultérieure) et ciblez la version Windows SDK 10.0.17134.0 (Windows 10, version 1803), puis un projet C++/WinRT nouvellement créé peut échouer à compiler 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 le mode de conformité du langage C/C++>Language>: Non (également, si /permissive- apparaît dans la propriété de projet C/C++>Language>Command Line sous Options supplémentaires, puis supprimez-le).

Démarrage rapide de C++/WinRT

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

Modifiez pch.h et main.cpp pour qu’ils ressemblent à 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. Mais il n'existe aucune dépendance stricte sur le kit SDK Windows, car votre projet (via lcppwinrt.exe'outil) 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 les API Windows projetées vers C++/WinRT. En d’autres termes, pour chaque type Windows, C++/WinRT définit un équivalent plus convivial pour C++ (appelé le 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 directives d’inclusion dans votre en-tête précompilé réduit les temps de compilation incrémentielle.

Important

Chaque fois que vous souhaitez utiliser un type provenant d’un espace de noms Windows, vous devez #include inclure le fichier d’en-tête de l’espace de noms Windows C++/WinRT correspondant, comme indiqué ci-dessus. L’en-tête correspondant est celui portant 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 ::P ropertySet, incluez l’en-têtewinrt/Windows.Foundation.Collections.h.

Il est courant qu’un fichier d’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 using namespace directives 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, en revanche, vous mélangez du code C++/WinRT avec du code C++/CX et/ou du code d’interface binaire d’application (ABI) du SDK (vous migrez depuis l’un ou l’autre de ces modèles, ou assurez l’interopérabilité avec l’un d’eux, voire avec les deux), consultez alors les rubriques Interopérabilité entre C++/WinRT et C++/CX, Passer de C++/CX à C++/WinRT et Interopérabilité entre C++/WinRT et l’ABI.

winrt::init_apartment();

L’appel à winrt::init_apartment initialise le thread au sein de 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 : ils correspondent à l’URI du blog Windows et à 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 appelle obtenir sur cet objet pour bloquer le thread 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 renvoyés par les fonctions begin et end (ou leurs variantes constantes, inversées et constantes inversées). Pour cette raison, vous pouvez énumérer Items à l’aide d’une instruction for basée sur une plage, ou avec la fonction modèle std::for_each. Chaque fois que vous effectuez une itération sur une collection Windows Runtime comme celle-ci, vous devrez #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, en tant qu’objet winrt ::hstring (plus de détails dans la gestion des chaînes en C++/WinRT). La chaîne hstring est ensuite sortie, 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 modernes et de classe, C++ 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 de bureau Windows 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 de 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 de bureau Windows que vous avez peut-être. Si vous n'avez pas de projet d'application de bureau Windows existant, vous pouvez suivre ces étapes en créant d'abord un projet d'application de bureau. Par exemple, ouvrez Visual Studio et créez un projet Visual C++>Windows Desktop>Application de bureau Windows.

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

Définir les propriétés du projet

Accédez à la propriété de projet General>Windows SDK Version, puis sélectionnez Toutes les configurations et toutes les plateformes. Vérifiez que Windows version du SDK 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++>Langage>Norme du langage C++ sur la valeur 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é du projet C/C++>En-têtes précompilés>En-tête précompilé sur Créer (/Yc), et la propriété Fichier d’en-tête précompilé sur pch.h.

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

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

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

Connexion

La projection de langage C++/WinRT dépend de certaines fonctions libres (non membres) et de certains points d’entrée de Windows Runtime, qui nécessitent une liaison avec la bibliothèque parapluie 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 le package NuGet Microsoft.Windows.CppWinRT dans votre projet. Ouvrez le project dans Visual Studio, cliquez sur Project>Manage de packages NuGet...>Parcourez, 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 cette project.

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, et ajouter du code C++/WinRT à votre projet (par exemple, du code similaire à celui présenté dans la section démarrage rapide A 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 utilisant ou en appelant des API. 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 Utiliser des API avec C++/WinRT.

Création d’API et de types Windows

En d’autres termes, la production d’API et de 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 effectuer cette opération dans les contrôles XAML ; liaison à une propriété C++/WinRT.

Applications 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 le framework dominant de l’interface utilisateur sur Windows aujourd’hui, et son influence sur le 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. Les bons emplacements de démarrage sont des contrôles XAML ; liez-vous à une propriété C++/WinRT et à des contrôles XAML personnalisés (basés sur des 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