Freigeben über


Erste Schritte mit C++/WinRT

Von Bedeutung

Informationen zum Einrichten von Visual Studio für die C++/WinRT-Entwicklung – einschließlich der Installation und Verwendung der C++/WinRT Visual Studio-Erweiterung (VSIX) und des NuGet-Pakets (die zusammen Projektvorlagen und Build-Unterstützung bereitstellen) – finden Sie unter Visual Studio-Unterstützung für C++/WinRT.

Um Ihnen den Einstieg in die Nutzung von C++/WinRT-zu erleichtern, führt dieses Thema durch ein einfaches Codebeispiel, das auf einem neuen Windows-Konsolenanwendungsprojekt (C++/WinRT) basiert. In diesem Thema wird auch gezeigt, wie Sie Unterstützung für C++/WinRT zu einem Windows-Desktop-Anwendungsprojekt hinzufügen.

Hinweis

Es wird empfohlen, mit den neuesten Versionen von Visual Studio und dem Windows SDK zu entwickeln, wenn Sie jedoch Visual Studio 2017 (Version 15.8.0 oder höher) verwenden und die Windows SDK-Version 10.0.17134.0 (Windows 10, Version 1803) anvisieren, kann ein neu erstelltes C++/WinRT-Projekt möglicherweise mit dem Fehler "Fehler C3861: 'from_abi': Bezeichner nicht gefunden" und mit anderen Fehlern, die aus base.hstammen, nicht kompiliert werden. Die Lösung besteht darin, entweder auf eine spätere (konformere) Version des Windows SDK abzuzielen oder die Projekteigenschaft C/C++>Sprache>Konformitätsmodus auf Nein zu stellen (auch, wenn /permissive- in der Projekteigenschaft C/C++>Sprache>Befehlszeile unter Zusätzliche Optionenangezeigt wird, dann löschen).

Ein C++/WinRT-Schnellstart

Erstellen Sie ein neues Windows Console Application (C++/WinRT) Projekt.

Bearbeiten Sie pch.h und main.cpp, damit sie so aussehen.

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

Nehmen wir uns das kurze Codebeispiel oben stück für Stück an und erläutern, was in den einzelnen Teilen passiert.

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

Mit den Standardprojekteinstellungen stammen die enthaltenen Header aus dem Windows SDK, innerhalb des Ordners %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio enthält diesen Pfad in seinem IncludePath--Makro. Es gibt jedoch keine strikte Abhängigkeit vom Windows SDK, da Ihr Projekt (über das cppwinrt.exe Tool) dieselben Header in den $(GeneratedFilesDir)- Ordner Ihres Projekts generiert. Sie werden aus diesem Ordner geladen, wenn sie an anderer Stelle nicht gefunden werden können, oder wenn Sie Ihre Projekteinstellungen ändern.

Die Header enthalten Windows-APIs, die in C++/WinRT projiziert werden. Mit anderen Worten: Für jeden Windows-Typ definiert C++/WinRT ein C++-freundliches Äquivalent (den projizierten Typ). Ein projizierter Typ hat den gleichen vollqualifizierten Namen wie der Windows-Typ, wird jedoch im C++-winrt Namespace platziert. Wenn Sie diese Elemente in den vorkompilierten Header einfügen, werden die inkrementellen Aufbauzeiten reduziert.

Von Bedeutung

Wann immer Sie einen Typ aus einem Windows-Namespace verwenden möchten, müssen Sie die entsprechende C++/WinRT Windows-Namespaceheaderdatei #include, wie oben gezeigt. Die entsprechenden-Header sind diejenigen mit demselben Namen wie der Namespace des Typs. Wenn Sie beispielsweise die C++/WinRT-Projektion für die Windows::Foundation::Collections::PropertySet Runtime-Klasse verwenden möchten, schließen Sie die winrt/Windows.Foundation.Collections.h Kopfzeile ein.

Es ist üblich, dass ein C++/WinRT-Projektionsheader automatisch verwandte Namespaceheaderdateien enthält. Beispielsweise winrt/Windows.Foundation.Collections.h enthält winrt/Windows.Foundation.h. Sie sollten sich jedoch nicht auf dieses Verhalten verlassen, da es sich um ein Implementierungsdetails handelt, das sich im Laufe der Zeit ändert. Sie müssen explizit alle Kopfzeilen einschließen, die Sie benötigen.

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

Die using namespace Direktiven sind optional, aber praktisch. Das oben gezeigte Muster für solche Direktiven (das Zulassen einer nicht qualifizierten Namenssuche für alle Elemente im winrt Namespace) eignet sich für den Beginn eines neuen Projekts, und C++/WinRT ist die einzige Sprachprojektion, die Sie innerhalb dieses Projekts verwenden. Wenn Sie dagegen C++/WinRT-Code mit C++/CX- und/oder SDK-Anwendungs-Binärschnittstellencode (ABI)-Code mischen (Sie portieren entweder von einem oder beiden Modellen oder arbeiten mit ihnen zusammen), dann sehen Sie sich die Themen Interoperabilität zwischen C++/WinRT und C++/CX, Wechsel von C++/CX zu C++/WinRT, und Interoperabilität zwischen C++/WinRT und der ABIan.

winrt::init_apartment();

Der Aufruf von winrt::init_apartment initialisiert den Thread in der Windows-Runtime; standardmäßig in einer Multithread-Wohnung. Der Aufruf initialisiert auch COM.

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

Allokiere zwei Objekte auf dem Stack: Sie repräsentieren die URI des Windows-Blogs und einen Syndikations-Client. Wir erstellen den URI mit einem einfachen breiten Zeichenfolgenliteral (siehe Zeichenfolgenbehandlung in C++/WinRT für weitere Möglichkeiten zum Arbeiten mit Zeichenfolgen).

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

SyndicationClient::RetrieveFeedAsync ist ein Beispiel für eine asynchrone Windows-Runtime-Funktion. Das Codebeispiel empfängt ein asynchrones Vorgangsobjekt von RetrieveFeedAsync-und ruft abrufen für dieses Objekt auf, um den aufrufenden Thread zu blockieren und auf das Ergebnis zu warten (in diesem Fall ein Syndication-Feed). Weitere Informationen über Parallelität und nicht blockierende Techniken finden Sie unter Parallelität und asynchrone Operationen mit C++/WinRT.

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

SyndicationFeed.Items ist ein Bereich, der durch die von den Funktionen begin und end (oder deren konstante, umgekehrte und konstante-umgekehrte Varianten) zurückgegebenen Iteratoren definiert wird. Aus diesem Grund können Sie -Artikel entweder mit einer bereichsbasierten for-Anweisung oder mit der std::for_each-Schablonenfunktion aufzählen. Wenn Sie wie folgt eine Windows-Runtime-Auflistung durchlaufen, müssen Sie #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;

Ruft den Titeltext des Feeds als winrt::hstring-Objekt ab (weitere Einzelheiten unter Zeichenfolgenbehandlung in C++/WinRT). Die hstring wird dann über die c_str Funktion ausgegeben, die das bei C++-Standardbibliothekszeichenfolgen verwendete Muster widerspiegelt.

Wie Sie sehen können, fördert C++/WinRT moderne und klassenähnliche C++-Ausdrücke wie syndicationItem.Title().Text(). Dies ist ein anderer und saubererer Programmierstil von herkömmlicher COM-Programmierung. Sie müssen COM nicht direkt initialisieren oder mit COM-Zeigern arbeiten.

Sie müssen auch keine HRESULT-Rückgabecodes behandeln. C++/WinRT konvertiert Fehler-HRESULTs in Ausnahmen, beispielsweise winrt::hresult-error, für einen natürlichen und modernen Programmierstil. Weitere Informationen zur Fehlerbehandlung und Codebeispielen finden Sie unter Fehlerbehandlung mit C++/WinRT.

Ändern eines Windows-Desktopanwendungsprojekts zum Hinzufügen der C++/WinRT-Unterstützung

Einige Desktopprojekte (z. B. die WinUI 3-Vorlagen in Visual Studio) verfügen über integrierte C++/WinRT-Unterstützung.

In diesem Abschnitt wird jedoch gezeigt, wie Sie C++/WinRT-Unterstützung zu einem beliebigen Windows-Desktopanwendungsprojekt hinzufügen können, das Sie möglicherweise haben. Wenn Sie nicht über ein vorhandenes Windows-Desktopanwendungsprojekt verfügen, können Sie diese Schritte ausführen, indem Sie zuerst eins erstellen. Öffnen Sie beispielsweise Visual Studio und erstellen Sie ein Projekt vom Typ Visual C++->Windows-Desktop>Windows-Desktop-Anwendung.

Optional können Sie die C++/WinRT Visual Studio Extension (VSIX) und das NuGet-Paket installieren. Ausführliche Informationen finden Sie unter Visual Studio-Unterstützung für C++/WinRT.

Festlegen von Projekteigenschaften

Wechseln Sie zur Projekteigenschaft Allgemeine>Windows SDK-Version, und wählen Sie Alle Konfigurationen und Alle Plattformenaus. Stellen Sie sicher, dass Windows SDK-Version auf 10.0.17134.0 (Windows 10, Version 1803) oder höher festgelegt ist.

Vergewissern Sie sich, dass Sie nicht von dem Problem "Warum wird mein neues Projekt nicht kompiliert?"betroffen sind.

Da C++/WinRT Features aus dem C++17-Standard verwendet, legen Sie die Projekteigenschaft C/C++>Language>C++-Sprachstandard auf ISO C++17 Standard (/std:c++17)fest.

Der vorkompilierte Header

Die Standardprojektvorlage erstellt eine vorkompilierte Kopfzeile für Sie, die entweder framework.hoder stdafx.hbenannt ist. Benennen Sie das in pch.hum. Wenn Sie über eine stdafx.cpp Datei verfügen, benennen Sie sie in pch.cppum. Legen Sie die Projekteigenschaft C/C++>Vorkompilierte Header>vorkompilierten Header- auf Erstellen (/Yc)-fest, und Vorkompilierte Headerdatei auf pch.h.

Suchen und ersetzen Sie alle #include "framework.h" (oder #include "stdafx.h") durch #include "pch.h".

Schließen Sie in pch.hwinrt/base.hein.

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

Verlinkung

Die C++/WinRT-Sprachprojektion hängt von bestimmten freien (nicht-Mitglied) Windows-Runtime-Funktionen und Einstiegspunkten ab, die eine Verknüpfung mit der WindowsApp.lib-Dachbibliothek erfordern. In diesem Abschnitt werden drei Möglichkeiten beschrieben, um den Linker zu befriedigen.

Die erste Option besteht darin, Ihrem Visual Studio-Projekt alle C++/WinRT MSBuild-Eigenschaften und -Ziele hinzuzufügen. Installieren Sie dazu das Microsoft.Windows.CppWinRT NuGet-Paket in Ihrem Projekt. Öffnen Sie das Projekt in Visual Studio, klicken Sie auf Projekt>NuGet-Pakete verwalten...>Durchsuchen Sie, geben Sie Microsoft.Windows.CppWinRT im Suchfeld ein, wählen Sie das Element in den Suchergebnissen aus, und klicken Sie dann auf Installieren, um das Paket für dieses Projekt zu installieren.

Sie können auch die Projektlinkeinstellungen verwenden, um WindowsApp.libexplizit zu verknüpfen. Sie können dies auch im Quellcode (z. B. in pch.h) wie folgt tun.

#pragma comment(lib, "windowsapp")

Sie können nun C++/WinRT-Code zu Ihrem Projekt kompilieren und verknüpfen (z. B. Code, der im A C++/WinRT-Schnellstart Abschnitt oben gezeigt wird).

Die drei Hauptszenarien für C++/WinRT

Wenn Sie sich mit C++/WinRT vertraut machen und die restliche Dokumentation hier durcharbeiten, werden Sie wahrscheinlich feststellen, dass es drei Hauptszenarien gibt, wie in den folgenden Abschnitten beschrieben.

Verwenden von Windows-APIs und -Typen

Mit anderen Worten: mitoder APIs aufrufen. Beispielsweise API-Aufrufe tätigen, um mit Bluetooth zu kommunizieren; zum Streamen und Präsentieren von Videos; zur Integration in die Windows-Shell; und so weiter. C++/WinRT unterstützt diese Szenariokategorie vollständig und kompromisslos. Weitere Informationen finden Sie unter Nutzen von APIs mit C++/WinRT.

Erstellen von Windows-APIs und -Typen

Mit anderen Worten: APIs und Typen produzieren. Erstellen Sie z. B. die arten von APIs, die im obigen Abschnitt beschrieben sind; oder die Grafik-APIs; die Speicher- und Dateisystem-APIs; die Netzwerk-APIs usw. Weitere Informationen finden Sie unter Autoren-APIs mit C++/WinRT.

Das Erstellen von APIs mit C++/WinRT ist etwas aufwändiger als deren Verwendung, da Sie IDL verwenden müssen, um die Struktur der API zu definieren, bevor Sie sie implementieren können. In XAML-Steuerelementen gibt es eine durchgehende Anleitung; binden Sie an eine C++/WinRT-Eigenschaft.

XAML-Anwendungen

In diesem Szenario geht es um das Erstellen von Anwendungen und Steuerelementen im XAML-UI-Framework. Die Arbeit in einer XAML-Anwendung besteht aus einer Kombination von Verwendung und Erstellung. Da XAML jedoch heute das dominante UI-Framework unter Windows ist und sein Einfluss auf die Windows-Runtime entsprechend ist, verdient es eine eigene Szenariokategorie.

Beachten Sie, dass XAML am besten mit Programmiersprachen funktioniert, die Spiegelung bieten. In C++/WinRT müssen Sie manchmal etwas zusätzliche Arbeit ausführen, um mit dem XAML-Framework zu arbeiten. Alle diese Fälle werden in der Dokumentation behandelt. Gute Ausgangspunkte sind z.B. XAML-Steuerelemente, das Binden an eine C++/WinRT-Eigenschaft und benutzerdefinierte (vorlagenbasierte) XAML-Steuerelemente mit C++/WinRT.

Beispiel-Apps, die in C++/WinRT geschrieben wurden

Siehe Wo finde ich C++/WinRT-Beispiel-Apps?.

Wichtige APIs