Udostępnij za pomocą


Wprowadzenie do języka C++/WinRT

Ważne

Aby uzyskać informacje na temat konfigurowania programu Visual Studio dla programowania w języku C++/WinRT — w tym instalowania i używania rozszerzenia C++/WinRT Visual Studio (VSIX) oraz pakietu NuGet (który razem zapewnia obsługę szablonu projektu i kompilacji) — zobacz obsługa programu Visual Studio dla języka C++/WinRT.

Aby przyspieszyć korzystanie z C++/WinRT, w tym temacie przedstawiono prosty przykład kodu oparty na nowym projekcie Windows Console Application (C++/WinRT). W tym temacie pokazano również, jak dodać obsługę języka C++/WinRT do projektu aplikacji desktopowej systemu Windows.

Uwaga / Notatka

Chociaż zalecamy programowanie przy użyciu najnowszych wersji programu Visual Studio i zestawu Windows SDK, Jeśli używasz programu Visual Studio 2017 (wersja 15.8.0 lub nowsza) i jest przeznaczona dla zestawu Windows SDK w wersji 10.0.17134.0 (Windows 10, wersja 1803), wówczas nowo utworzony projekt C++/WinRT może zakończyć się niepowodzeniem kompilacji z błędem "błąd C3861: "from_abi": Nie odnaleziono identyfikatora", a inne błędy pochodzące z base.h. Rozwiązaniem jest ukierunkowanie nowszej (bardziej zgodnej) wersji zestawu Windows SDK lub ustawienie właściwości projektu C/C++ języka>C/C++>Tryb zgodności: nie (również jeśli /permissive- pojawia się we właściwości projektu C/C>++>wiersza polecenia w dodatkowych opcji, następnie usuń go).

Szybki start dla języka C++/WinRT

Utwórz nowy projekt aplikacji konsolowej systemu Windows (C++/WinRT).

Edytuj pch.h i main.cpp, aby wyglądać następująco.

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

Przeanalizujmy krótki przykład kodu zamieszczony powyżej, kawałek po kawałku, i wyjaśnijmy, co dzieje się w każdej części.

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

W przypadku domyślnych ustawień projektu dołączone nagłówki pochodzą z zestawu Windows SDK w folderze %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Program Visual Studio uwzględnia tę ścieżkę w makrze IncludePath. Nie ma jednak ścisłej zależności od zestawu Windows SDK, ponieważ projekt (za pośrednictwem narzędzia cppwinrt.exe) generuje te same nagłówki w folderze $(GeneratedFilesDir). Zostaną one załadowane z tego folderu, jeśli nie zostaną znalezione w innym miejscu lub jeśli zmienisz ustawienia projektu.

Nagłówki zawierają interfejsy API systemu Windows odwzorowane w języku C++/WinRT. Innymi słowy, dla każdego typu systemu Windows C++/WinRT definiuje przyjazny dla języka C++ odpowiednik (nazywany projekcjowanym typem). Typ przewidywany ma taką samą w pełni kwalifikowaną nazwę jak typ systemu Windows, ale znajduje się w przestrzeni nazw winrt języka C++. Umieszczenie tych elementów w prekompilowanych nagłówkach zmniejsza czas kompilacji przyrostowej.

Ważne

Zawsze, gdy chcesz użyć typu z przestrzeni nazw systemu Windows, musisz #include odpowiedniego pliku nagłówka przestrzeni nazw systemu Windows C++/WinRT, jak pokazano powyżej. Nagłówek odpowiadający to ten, który ma taką samą nazwę jak przestrzeń nazw typu. Aby na przykład użyć projekcji C++/WinRT dla Windows::Foundation::Collections::P ropertySet klasy środowiska uruchomieniowego, dołącz nagłówek winrt/Windows.Foundation.Collections.h.

Nagłówki projekcji C++/WinRT często automatycznie dołączają powiązane pliki nagłówkowe przestrzeni nazw. Na przykład winrt/Windows.Foundation.Collections.h zawiera winrt/Windows.Foundation.h. Nie należy jednak polegać na tym zachowaniu, ponieważ jest to szczegóły implementacji, które zmieniają się w czasie. Musisz wyraźnie dołączyć wszystkie nagłówki, które są potrzebne.

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

Dyrektywy using namespace są opcjonalne, ale wygodne. Wzorzec przedstawiony powyżej dla tego typu dyrektyw (zezwalający na niekwalifikowane wyszukiwanie nazw dla wszystkich elementów w przestrzeni nazw winrt) jest odpowiedni, gdy zaczynasz nowy projekt, a C++/WinRT jest jedyną używaną w nim projekcją języka. Jeśli łączysz kod C++/WinRT z C++/CX i/lub kod binarny interfejsu aplikacji (ABI) SDK i (przenosisz się z jednego z tych modeli lub współpracujesz z nimi), zapoznaj się z tematami Interoperacyjność między C++/WinRT a C++/CX, Przejście do C++/WinRT z C++/CXoraz Interoperacyjność między C++/WinRT a ABI.

winrt::init_apartment();

Wywołanie metody winrt::init_apartment inicjuje wątek w środowisku uruchomieniowym systemu Windows; domyślnie w wielowątkowym apartamencie. Wywołanie również inicjuje COM.

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

Przypisz na stosie dwa obiekty: reprezentują one uri bloga Windows oraz klienta syndykacji. Tworzymy identyfikator URI przy użyciu literału prostego szerokiego ciągu znaków (zobacz rozdział Obsługa ciągów w języku C++/WinRT, aby poznać inne sposoby pracy z ciągami).

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

SyndicationClient::RetrieveFeedAsync jest przykładem asynchronicznej funkcji środowiska uruchomieniowego systemu Windows. Przykładowy kod odbiera obiekt operacji asynchronicznej z RetrieveFeedAsynci wywołuje get na tym obiekcie w celu zablokowania wątka wykonawczego i poczekania na wynik (który w tym przypadku jest kanałem informacyjnym). Aby uzyskać więcej informacji na temat współbieżności i technik nieblokujących, zobacz współbieżność i operacje asynchroniczne w języku C++/WinRT.

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

SyndicationFeed.Items jest zakresem zdefiniowanym przez iteratory zwrócone z funkcji begin i end (lub ich stałe, odwrotne i stałe-odwrotne warianty). W związku z tym można wyliczyć Items za pomocą instrukcji for opartej na zakresie lub funkcji szablonu std::for_each. Za każdym razem, gdy iterujesz kolekcję środowiska uruchomieniowego systemu Windows w następujący sposób, musisz #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;

Pobiera tekst tytułu kanału informacyjnego jako obiekt winrt::hstring (więcej szczegółów w obsłudze ciągów w języku C++/WinRT). Plik hstring jest następnie wyprowadzany za pomocą funkcji c_str, która odzwierciedla schemat stosowany w przypadku ciągów z biblioteki standardowej C++.

Jak widać, język C++/WinRT zachęca do nowoczesnych i podobnych do klas wyrażeń języka C++, takich jak syndicationItem.Title().Text(). Jest to inny, czystszy styl programowania od tradycyjnego programowania COM. Nie musisz bezpośrednio inicjować COM ani pracować ze wskaźnikami COM.

Nie trzeba również obsługiwać kodów zwrotu HRESULT. C++/WinRT konwertuje błędy HRESULTs na wyjątki, takie jak winrt::hresult-error dla naturalnego i nowoczesnego stylu programowania. Aby uzyskać więcej informacji na temat obsługi błędów i przykładów kodu, zobacz Obsługa błędów w języku C++/WinRT.

Modyfikowanie projektu aplikacji klasycznej systemu Windows w celu dodania obsługi języka C++/WinRT

Niektóre projekty klasyczne (na przykład szablony WinUI 3 w programie Visual Studio) mają wbudowaną obsługę języka C++/WinRT.

Ta sekcja pokazuje, jak można dodać obsługę języka C++/WinRT do każdego projektu aplikacji desktopowej Windows, który możesz mieć. Jeśli nie masz istniejącego projektu aplikacji klasycznej systemu Windows, możesz wykonać te kroki, tworząc go najpierw. Na przykład otwórz program Visual Studio i utwórz projekt Visual C++>Aplikacja klasyczna systemu Windows>.

Możesz opcjonalnie zainstalować rozszerzenie C++/WinRT Visual Studio Extension (VSIX) oraz pakiet NuGet. Aby uzyskać szczegółowe informacje, zobacz wsparcie programu Visual Studio dla języka C++/WinRT.

Ustawianie właściwości projektu

Przejdź do właściwości projektu Ogólne>Wersja zestawu narzędzi Windows SDKi wybierz pozycję Wszystkie konfiguracje i Wszystkie platformy. Upewnij się, że wersja Windows SDK jest ustawiona na 10.0.17134.0 (Windows 10, wersja 1803) lub nowszej.

Upewnij się, że nie dotyczy Cię Dlaczego mój nowy projekt nie zostanie skompilowany?.

Ponieważ język C++/WinRT używa funkcji ze standardu C++17, ustaw właściwość projektu C/C++>Language>C++ Language Standard w celu standardu ISO C++17 Standard (/std:c++17).

Prekompilowany nagłówek

Domyślny szablon projektu tworzy prekompilowany nagłówek o nazwie framework.hlub stdafx.h. Zmień nazwę na pch.h. Jeśli masz plik stdafx.cpp, zmień jego nazwę na pch.cpp. Ustaw właściwość projektu prekompilowanych nagłówków C/C++prekompilowanychprekompilowanych nagłówków utwórz (/Yc)i prekompilowany plik nagłówka na pch.h.

Znajdź i zastąp wszystkie #include "framework.h" (lub #include "stdafx.h") na #include "pch.h".

W pch.huwzględnij winrt/base.h.

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

Łączenie

Projekcja języka C++/WinRT zależy od niektórych wolnostojących funkcji Windows Runtime i punktów wejścia, które wymagają połączenia z biblioteką parasolową WindowsApp.lib. W tej sekcji opisano trzy sposoby zaspokojenia programu łączącego.

Pierwszą opcją jest dodanie do projektu programu Visual Studio wszystkich właściwości i obiektów docelowych C++/WinRT MSBuild. W tym celu zainstaluj pakiet NuGet Microsoft.Windows.CppWinRT w projekcie. Otwórz projekt w programie Visual Studio, kliknij Project>Manage NuGet Packages...>Browse, wpisz lub wklej Microsoft.Windows.CppWinRT w polu wyszukiwania, wybierz element w wynikach wyszukiwania, a następnie kliknij Zainstaluj, aby zainstalować pakiet dla tego projektu.

Możesz również użyć ustawień linku projektu, aby bezpośrednio powiązać WindowsApp.lib. Możesz też to zrobić w kodzie źródłowym (na przykład w pch.h, na przykład).

#pragma comment(lib, "windowsapp")

Teraz możesz kompilować i linkować oraz dodawać kod C++/WinRT do swojego projektu (na przykład kod podobny do przedstawionego w sekcji szybki start C++/WinRT powyżej).

Trzy główne scenariusze dla języka C++/WinRT

Korzystając z języka C++/WinRT i zapoznasz się z resztą dokumentacji tutaj, prawdopodobnie zauważysz, że istnieją trzy główne scenariusze, zgodnie z opisem w poniższych sekcjach.

Korzystanie z interfejsów API i typów systemu Windows

Innymi słowy, używającz lub wywołując z . Na przykład wykonywanie wywołań interfejsu API w celu komunikowania się przez Bluetooth, przesyłania strumieniowego i prezentowania wideo, integracji z powłoką systemu Windows i tak dalej. Język C++/WinRT w pełni i bezkompromisowo obsługuje tę kategorię scenariusza. Aby uzyskać więcej informacji, zobacz Korzystanie z interfejsów API za pomocą języka C++/WinRT.

Autoryzowanie interfejsów API i typów systemu Windows

Innymi słowy, tworzenia interfejsów API i typów. Na przykład tworzenie rodzajów interfejsów API opisanych w powyższej sekcji, interfejsów API grafiki, interfejsów API magazynowania i systemu plików, interfejsów API sieci itd. Aby uzyskać więcej informacji, zobacz Author APIs with C++/WinRT.

Tworzenie interfejsów API za pomocą języka C++/WinRT jest nieco bardziej zaangażowane niż korzystanie z nich, ponieważ należy użyć języka IDL do zdefiniowania kształtu interfejsu API przed jego zaimplementowaniem. W kontrolkach XAML znajduje się przewodnik dotyczący powiązania z właściwością C++/WinRT.

Aplikacje XAML

Ten scenariusz dotyczy tworzenia aplikacji i kontrolek w strukturze interfejsu użytkownika XAML. Praca w aplikacji XAML jest kombinacją używania i tworzenia. Jednak ponieważ XAML jest obecnie dominującą strukturą interfejsu użytkownika w systemie Windows, a jej wpływ na środowisko uruchomieniowe systemu Windows jest proporcjonalny do tego, zasługuje na własną kategorię scenariusza.

Należy pamiętać, że język XAML działa najlepiej z językami programowania, które oferują refleksję. W języku C++/WinRT czasami trzeba wykonać trochę dodatkowej pracy w celu współdziałania ze strukturą XAML. Wszystkie te przypadki zostały omówione w dokumentacji. Dobre miejsca do rozpoczęcia to kontrolki XAML ; wiązanie do właściwości C++/WinRT i kontrolki niestandardowe XAML (szablonowe) z C++/WinRT .

Przykładowe aplikacje napisane w języku C++/WinRT

Zobacz Gdzie można znaleźć przykładowe aplikacje C++/WinRT?.

Ważne interfejsy API