Aan de slag met C++/WinRT

Belangrijk

Zie Visual Studio support for C++/WinRT voor informatie over het configureren van Visual Studio voor C++/WinRT-ontwikkeling, waaronder het installeren en gebruiken van de C++/WinRT Visual Studio-extensie (VSIX) en het NuGet-pakket (die samen projectsjablonen en ondersteuning voor builds bieden).

Om u op de hoogte te stellen van het gebruik van C++/WinRT, doorloopt dit onderwerp een eenvoudig codevoorbeeld op basis van een nieuw Windows Console Application-project (C++/WinRT). In dit onderwerp wordt ook beschreven hoe u C++/WinRT-ondersteuning toevoegt aan een Windows Bureaubladtoepassingsproject.

Note

We raden u aan om te ontwikkelen met de nieuwste versies van Visual Studio en de Windows SDK, als u Visual Studio 2017 (versie 15.8.0 of hoger) gebruikt en gericht bent op de Windows SDK-versie 10.0.17134.0 (Windows 10, versie 1803), dan kan een nieuw C++/WinRT-project niet worden gecompileerd met de fout 'fout C3861: 'from_abi': id niet gevonden' en met andere fouten die afkomstig zijn uit base.h. De oplossing is om een latere (meer conforme) versie van de Windows SDK te richten of de projecteigenschap C/C++>Language>Conformance-modus in te stellen: Nee (ook als /permissive- wordt weergegeven in projecteigenschap C/C++>Language>Command Line onder Aanvullende opties en vervolgens verwijderen).

Snel aan de slag met C++/WinRT

Maak een nieuw Windows Console Application-project (C++/WinRT).

Bewerk pch.h en main.cpp zodat ze er zo uitzien.

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

Laten we het korte codevoorbeeld hierboven stuk voor stuk bekijken en uitleggen wat er in elk deel gebeurt.

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

Met de standaardprojectinstellingen zijn de opgenomen headers afkomstig van de Windows SDK, in de map%WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio bevat dat pad in de macro IncludePath. Maar er is geen strikte afhankelijkheid van de Windows SDK, omdat uw project (via het cppwinrt.exe hulpprogramma) dezelfde headers genereert in de map $(GeneratedFilesDir) van uw project. Ze worden vanuit die map geladen als ze elders niet kunnen worden gevonden of als u de projectinstellingen wijzigt.

De headers bevatten Windows API's die zijn geprojecteerd in C++/WinRT. Met andere woorden, voor elk Windows-type definieert C++/WinRT een C++-vriendelijk equivalent (het zogeheten geprojecteerde type). Een geprojecteerd type heeft dezelfde volledig gekwalificeerde naam als het Windows type, maar wordt in de winrt-naamruimte C++ geplaatst. Door deze includebestanden in uw voorgecompileerde header op te nemen, verkort u de incrementele buildtijden.

Belangrijk

Wanneer u een type uit een Windows naamruimten wilt gebruiken, moet #include u het bijbehorende C++/WinRT-Windows naamruimteheaderbestand gebruiken, zoals hierboven wordt weergegeven. De bijbehorende header is degene met dezelfde naam als de naamruimte van het type. Als u bijvoorbeeld de C++/WinRT-projectie wilt gebruiken voor de runtimeklasse Windows::Foundation::Collections::PropertySet, neemt u het headerbestand winrt/Windows.Foundation.Collections.h op.

Het is gebruikelijk dat een C++/WinRT-projectieheader automatisch gerelateerde naamruimteheaderbestanden bevat. winrt/Windows.Foundation.Collections.h bevat bijvoorbeeld winrt/Windows.Foundation.h. Maar u moet niet vertrouwen op dit gedrag, omdat het een implementatiedetail is dat na verloop van tijd verandert. U moet expliciet eventuele headers opnemen die u nodig hebt.

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

De using namespace instructies zijn optioneel, maar handig. Het bovenstaande patroon voor dergelijke instructies (het toestaan van niet-gekwalificeerde naamzoekacties voor alles in de winrt-naamruimte ) is geschikt voor wanneer u een nieuw project start en C++/WinRT de enige taalprojectie is die u in dat project gebruikt. Als u daarentegen C++/WinRT-code combineert met C++/CX - en/of ABI-code (Binary Interface) van de SDK-toepassing (u wilt overzetten of samenwerken met een of beide modellen), raadpleegt u de onderwerpen tussen C++/WinRT en C++/CX, overstappen naar C++/WinRT van C++/CX en Interop tussen C++/WinRT en de ABI.

winrt::init_apartment();

De aanroep van winrt::init_apartment initialiseert de thread in de Windows Runtime; standaard in een appartement met meerdere threads. De aanroep initialiseert ook COM.

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

Alloceer twee objecten op de stack: die vertegenwoordigen de URI van de Windows-blog en een syndication-client. We bouwen de URI samen met een eenvoudige letterlijke tekenreeks (zie De verwerking van tekenreeksen in C++/WinRT voor meer manieren waarop u met tekenreeksen kunt werken).

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

SyndicationClient::RetrieveFeedAsync is een voorbeeld van een asynchrone Windows Runtime functie. Het codevoorbeeld ontvangt een object voor een asynchrone bewerking van RetrieveFeedAsync en roept get aan op dat object om de aanroepende thread te blokkeren en op het resultaat te wachten (in dit geval een syndicatiefeed). Zie Gelijktijdigheid en asynchrone bewerkingen met C++/WinRT voor meer informatie over gelijktijdigheid en voor niet-blokkerende technieken.

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

SyndicationFeed.Items is een bereik, gedefinieerd door de iterators die worden geretourneerd door de functies begin en end (of hun constante, omgekeerde en constant omgekeerde varianten). Daarom kunt u items opsommen met een op bereik gebaseerde for instructie of met de sjabloonfunctie std::for_each . Wanneer u een Windows Runtime-verzameling zoals dit doorloopt, moet u #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;

Hiermee haalt u de titeltekst van de feed op als een winrt::hstring-object (meer informatie over het verwerken van tekenreeksen in C++/WinRT). De hstring wordt vervolgens uitgevoerd via de functie c_str , die het patroon weerspiegelt dat wordt gebruikt met tekenreeksen van de standaardbibliotheek van C++ .

Zoals u kunt zien, moedigt C++/WinRT moderne en klasse-achtige C++-expressies aan, zoals syndicationItem.Title().Text(). Dit is een andere, en schonere programmeerstijl van traditionele COM-programmering. U hoeft COM niet rechtstreeks te initialiseren en niet met COM-aanwijzers te werken.

U hoeft ook geen HRESULT-retourcodes te verwerken. C++/WinRT converteert fout HRESULTs naar uitzonderingen zoals winrt::hresult-error voor een natuurlijke en moderne programmeerstijl. Zie Foutafhandeling met C++/WinRT voor meer informatie over foutafhandeling en codevoorbeelden.

Een Windows Bureaubladtoepassingsproject wijzigen om C++/WinRT-ondersteuning toe te voegen

Sommige bureaubladprojecten (bijvoorbeeld de WinUI 3-sjablonen in Visual Studio) hebben C++/WinRT-ondersteuning ingebouwd.

In deze sectie ziet u echter hoe u C++/WinRT-ondersteuning kunt toevoegen aan elk Windows Bureaubladtoepassingsproject dat u mogelijk hebt. Als u geen bestaand Windows bureaubladtoepassingsproject hebt, kunt u deze stappen volgen door er eerst een te maken. Open bijvoorbeeld Visual Studio en maak een Visual C++>Windows Desktop>Windows Bureaubladtoepassingsproject.

U kunt eventueel de C++/WinRT-Visual Studio-extensie (VSIX) en het NuGet-pakket installeren. Zie Visual Studio ondersteuning voor C++/WinRT voor meer informatie.

Projecteigenschappen instellen

Ga naar de projecteigenschap Algemeen>Windows SDK-versie en selecteer Alle configuraties en alle platforms. Zorg ervoor dat Windows SDK-versie is ingesteld op 10.0.17134.0 (Windows 10, versie 1803) of hoger.

Controleer of dit niet wordt beïnvloed door Waarom wordt mijn nieuwe project niet gecompileerd?.

Omdat C++/WinRT gebruikmaakt van functies van de C++17-standaard, stelt u projecteigenschap C/C++>Language>C++ Language Standard in op ISO C++17 Standard (/std:c++17).

De vooraf gecompileerde header

Met de standaardprojectsjabloon wordt een vooraf gecompileerde header voor u gemaakt, met de framework.hnaam of stdafx.h. Wijzig de naam ervan in pch.h. Als u een stdafx.cpp bestand hebt, wijzigt u de naam ervan in pch.cpp. Stel de projecteigenschap C/C++>Precompiled Headers>Precompiled Header in op Maken (/Yc), en Precompiled headerbestand op pch.h.

Zoek en vervang alle #include "framework.h" (of #include "stdafx.h") door #include "pch.h".

Neem winrt/base.h op in pch.h.

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

Koppelen

De C++/WinRT-taalprojectie is afhankelijk van bepaalde Windows Runtime gratis (niet-lid) functies en toegangspunten die moeten worden gekoppeld aan de WindowsApp.lib umbrella-bibliotheek. In deze sectie worden drie manieren beschreven om aan de vereisten van de linker te voldoen.

De eerste optie is om alle C++/WinRT MSBuild-eigenschappen en -doelen toe te voegen aan uw Visual Studio project. Installeer hiervoor de Microsoft.Windows. CppWinRT NuGet-pakket in uw project. Open het project in Visual Studio en klik op Project>Manage NuGet Packages...>Bladeren, typ of plak Microsoft.Windows.CppWinRT in het zoekvak, selecteer het item in de zoekresultaten en klik vervolgens op Installeren om het pakket voor dat project te installeren.

U kunt ook instellingen voor projectkoppelingen gebruiken om expliciet een koppeling te maken WindowsApp.lib. U kunt dit ook doen in broncode ( pch.hbijvoorbeeld in) zoals deze.

#pragma comment(lib, "windowsapp")

U kunt nu C++/WinRT-code compileren en koppelen aan uw project (bijvoorbeeld code die vergelijkbaar is met de code die wordt weergegeven in de snelstartsectie A C++/WinRT hierboven).

De drie belangrijkste scenario's voor C++/WinRT

Wanneer u C++/WinRT gebruikt en vertrouwd raakt en de rest van de documentatie hier doorloopt, zult u waarschijnlijk merken dat er drie hoofdscenario's zijn, zoals beschreven in de volgende secties.

Werken met Windows-API’s en -typen

Met andere woorden, het gebruik of het aanroepen van API's. Bijvoorbeeld het maken van API-aanroepen om te communiceren via Bluetooth; video streamen en presenteren; om te integreren met de Windows shell, enzovoort. C++/WinRT biedt volledige en compromisloze ondersteuning voor deze categorie scenario's. Zie API's gebruiken met C++/WinRT voor meer informatie.

Windows-API's en -typen ontwikkelen

Met andere woorden, het produceren van API's en typen. Bijvoorbeeld het produceren van de soorten API's die in de bovenstaande sectie worden beschreven; of de grafische API's; de opslag- en bestandssysteem-API's; de netwerk-API's, enzovoort. Zie Author-API's met C++/WinRT voor meer informatie.

API's schrijven met C++/WinRT is iets ingewikkelder dan ze gebruiken, omdat u IDL moet gebruiken om de structuur van de API te definiëren voordat u deze kunt implementeren. Er is een overzicht van dit in XAML-besturingselementen. Dit wordt gekoppeld aan een C++/WinRT-eigenschap.

XAML-toepassingen

Dit scenario gaat over het bouwen van toepassingen en besturingselementen in het XAML UI-framework. Werken in een XAML-toepassing komt neer op een combinatie van gebruiken en maken. Maar omdat XAML het dominante UI-framework is op Windows vandaag, en de invloed ervan op de Windows Runtime proportioneel is, verdient het een eigen categorie scenario.

Houd er rekening mee dat XAML het beste werkt met programmeertalen die reflectie bieden. In C++/WinRT moet u soms wat extra werk doen om te kunnen samenwerken met het XAML-framework. Al deze gevallen worden behandeld in de documentatie. Goede plaatsen om te beginnen zijn XAML-besturingselementen; binden aan een C++/WinRT-eigenschap en aangepaste (sjabloon)-besturingselementen met C++/WinRT.

Voorbeeld-apps geschreven in C++/WinRT

Zie waar vind ik C++-/WinRT-voorbeeld-apps?

Belangrijke API's