Condividi tramite


Introduzione a C++/WinRT

Importante

Per informazioni sulla configurazione di Visual Studio per lo sviluppo C++/WinRT, inclusa l'installazione e l'uso dell'estensione visual Studio C++/WinRT (VSIX) e del pacchetto NuGet (che insieme forniscono il modello di progetto e il supporto per la compilazione), vedere Supporto di Visual Studio per C++/WinRT.

Per familiarizzarti rapidamente con l'uso di C++/WinRT, questo argomento illustra un semplice esempio di codice basato su un nuovo progetto di Windows Console Application (C++/WinRT). Questo argomento mostra anche come aggiungere il supporto C++/WinRT a un progetto di applicazione desktop Windows.

Annotazioni

Anche se è consigliabile sviluppare con le versioni più recenti di Visual Studio e del Windows SDK, se utilizzi Visual Studio 2017 (versione 15.8.0 o successiva) e prendi di mira Windows SDK versione 10.0.17134.0 (Windows 10, versione 1803), un progetto C++/WinRT appena creato potrebbe non riuscire a compilare con l'errore "errore C3861: 'from_abi': identificatore non trovato" e con altri errori originati da base.h. La soluzione consiste nell'usare una versione successiva (più conforme) di Windows SDK o impostare la proprietà del progetto linguaggio C/C++modalità di conformità: nessuna (anche se /permissive- viene visualizzata nella proprietà del progetto linguaggio C/C++linguaggio nella Opzioni aggiuntive, quindi eliminarlo).

Guida rapida a C++/WinRT

Creare un nuovo progetto applicazione console di Windows (C++/WinRT) .

Modificare pch.h e main.cpp in modo che sia simile al seguente.

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

Si esaminerà ora l'esempio di codice breve precedente per frammento e si spieghererà cosa sta succedendo in ogni parte.

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

Con le impostazioni predefinite del progetto, le intestazioni incluse provengono dall'SDK di Windows, che si trovano all'interno della cartella %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt. Visual Studio include tale percorso nella macro IncludePath . Tuttavia, non esiste alcuna dipendenza rigorosa dal Windows SDK, perché il progetto (tramite lo strumento cppwinrt.exe) genera le stesse intestazioni nella cartella $(GeneratedFilesDir), del progetto. Verranno caricati da tale cartella se non sono disponibili altrove o se si modificano le impostazioni del progetto.

Le intestazioni contengono API di Windows proiettate in C++/WinRT. In altre parole, per ogni tipo di Windows, C++/WinRT definisce un equivalente compatibile con C++ (denominato tipo previsto). Un tipo proiettato ha lo stesso nome completo del tipo Windows, ma viene inserito nello spazio dei nomi C++ winrt. L'inserimento di queste inclusioni nell'header precompilato riduce i tempi di compilazione incrementale.

Importante

Ogni volta che vuoi usare un tipo da uno spazio dei nomi windows, devi #include il file di intestazione dello spazio dei nomi windows C++/WinRT corrispondente, come illustrato in precedenza. L'intestazione corrispondente è quella con lo stesso nome dello spazio dei nomi del tipo. Ad esempio, per usare la proiezione C++/WinRT per la classe di runtime Windows::Foundation::Collections::P ropertySet, includere l'intestazione winrt/Windows.Foundation.Collections.h.

È comune che un'intestazione di proiezione C++/WinRT includa automaticamente i file di intestazione delle relative namespace. Ad esempio, winrt/Windows.Foundation.Collections.h include winrt/Windows.Foundation.h. Ma non è consigliabile basarsi su questo comportamento, poiché si tratta di un dettaglio di implementazione che cambia nel tempo. È necessario includere in modo esplicito tutte le intestazioni necessarie.

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

Le direttive using namespace sono facoltative, ma utili. Il modello illustrato in precedenza per tali direttive (consentendo la ricerca di nomi non qualificati per qualsiasi elemento nello spazio dei nomi winrt ) è adatto quando si sta iniziando un nuovo progetto e C++/WinRT è l'unica proiezione del linguaggio in uso all'interno di tale progetto. Se, d'altra parte, si sta combinando il codice C++/WinRT con codice C++/CX e/o ABI (SDK Application Binary Interface) (si sta eseguendo la conversione da o l'interoperabilità con uno o entrambi i modelli), quindi vedere gli argomenti Interoperabilità tra C++/WinRT e C++/CX, Passare a C++/WinRT da C++/CX, e interoperabilità tra C++/WinRT e ABI.

winrt::init_apartment();

Per impostazione predefinita, la chiamata a winrt::init_apartment inizializza il thread in un apartment multithreaded di Windows Runtime. La chiamata inizializza anche COM.

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

Allocare nello stack due oggetti: rappresentano l'URI del blog di Windows e un client di syndication. Costruiamo l'URI con una semplice stringa letterale wide (vedi "gestione di stringhe" in C++/WinRT per altri modi di lavorare con le stringhe).

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

SyndicationClient::RetrieveFeedAsync è un esempio di una funzione di Windows Runtime asincrona. L'esempio di codice riceve un oggetto operazione asincrona da RetrieveFeedAsynce chiama get su tale oggetto per bloccare il thread chiamante e attendere il risultato (ovvero un feed di syndication, in questo caso). Per altre informazioni sulla concorrenza e per le tecniche non bloccanti, vedere Concorrenza e operazioni asincrone con C++/WinRT.

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

SyndicationFeed.Items è un intervallo definito dagli iteratori restituiti dalle funzioni inizio e fine (o dalle loro varianti costanti, inverse e inverse costanti). Per questo motivo, è possibile enumerare Items con un'istruzione basata su intervalli for o con la funzione modello std::for_each. Ogni volta che si esegue l'iterazione su una raccolta di Windows Runtime in questo modo, è necessario #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;

Ottiene il testo del titolo del feed, come oggetto winrt::hstring (altri dettagli nella gestione delle stringhe in C++/WinRT). La hstring viene quindi restituita tramite la funzione c_str, che riflette il modello usato con le stringhe della Libreria Standard C++.

Come si può notare, C++/WinRT incoraggia le espressioni C++ moderne e di tipo classe, ad esempio syndicationItem.Title().Text(). Si tratta di uno stile di programmazione diverso e pulito rispetto alla programmazione COM tradizionale. Non è necessario inizializzare direttamente COM, né usare i puntatori COM.

Né è necessario gestire i codici restituiti HRESULT. C++/WinRT converte gli HRESULT di errore in eccezioni come winrt::hresult-error per uno stile di programmazione moderno e naturale. Per altre info sulla gestione degli errori ed esempi di codice, vedi Gestione degli errori con C++/WinRT.

Modificare un progetto di applicazione Desktop di Windows per aggiungere il supporto C++/WinRT

Alcuni progetti desktop (ad esempio, i modelli WinUI 3 in Visual Studio) hanno il supporto C++/WinRT incorporato.

Questa sezione illustra tuttavia come aggiungere il supporto C++/WinRT a qualsiasi progetto di applicazione desktop di Windows che potresti avere. Se non si dispone di un progetto di applicazione Desktop di Windows esistente, è possibile seguire questi passaggi creandone uno. Ad esempio, aprire Visual Studio e creare un progetto di Visual C++>Windows Desktop>Windows Desktop Application.

Facoltativamente è possibile installare l'estensione C++/WinRT Visual Studio (VSIX) e il pacchetto NuGet. Per informazioni dettagliate, vedere supporto di Visual Studio per C++/WinRT.

Impostare le proprietà del progetto

Passare alla proprietà del progetto Versione Generale> diWindows SDK e selezionare Tutte le configurazioni e Tutte le piattaforme. Assicurarsi che Windows SDK versione sia impostata su 10.0.17134.0 (Windows 10, versione 1803) o superiore.

Conferma che non sei interessato da Perché il mio nuovo progetto non si compila?.

Poiché C++/WinRT usa funzionalità dello standard C++17, impostare la proprietà del progetto C/C++>Linguaggio>C++ Language Standard per ISO C++17 Standard (/std:c++17).

Intestazione precompilata

Il modello di progetto predefinito crea automaticamente un'intestazione precompilata, denominata framework.ho stdafx.h. Rinominarlo in pch.h. Se si dispone di un stdafx.cpp file, rinominarlo in pch.cpp. Impostare la proprietà del progetto C/C++>Intestazioni Precompilate>Intestazione Precompilata su Create (/Yc), e File di Intestazione Precompilato su pch.h.

Trovare e sostituire tutti #include "framework.h" (o #include "stdafx.h") con #include "pch.h".

Includi pch.hin winrt/base.h.

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

Collegamento

La proiezione del linguaggio C++/WinRT dipende da determinate funzioni gratuite (non membro) di Windows Runtime e punti di ingresso, che richiedono il collegamento alla libreria generica WindowsApp.lib. Questa sezione descrive tre modi per rispondere alle esigenze del linker.

La prima opzione consiste nell'aggiungere al progetto di Visual Studio tutte le proprietà e le destinazioni MSBuild C++/WinRT. A tale scopo, installare il pacchetto NuGet Microsoft.Windows.CppWinRT nel progetto. Aprire il progetto in Visual Studio, fare clic su Project>Manage NuGet Packages (>Gestisci pacchetti NuGet)Sfoglia, digita o incolla Microsoft.Windows.CppWinRT nella casella di ricerca, seleziona l'elemento nei risultati della ricerca e quindi fai clic su Installa per installare il pacchetto per il progetto.

È anche possibile utilizzare le impostazioni di collegamento al progetto per collegare WindowsApp.libin modo esplicito. In alternativa, è possibile farlo nel codice sorgente (in pch.h, ad esempio) in questo modo.

#pragma comment(lib, "windowsapp")

È ora possibile compilare e collegare e aggiungere codice C++/WinRT al progetto (ad esempio, codice simile a quello illustrato nella sezione Avvio rapido C++/WinRT precedente).

I tre scenari principali per C++/WinRT

Quando si utilizza e si diventa familiari con C++/WinRT e si continua a leggere la restante documentazione qui, probabilmente noterete che ci sono tre scenari principali, come descritto nelle sezioni seguenti.

Utilizzo delle API e dei tipi di Windows

In altre parole, usandoo chiamando le API di. Ad esempio, effettuare chiamate API per comunicare tramite Bluetooth; per trasmettere e presentare video; per l'integrazione con la shell di Windows; E così via. C++/WinRT supporta completamente e senza compromessi questa categoria di scenario. Per ulteriori informazioni, vedi Utilizzare API con C++/WinRT.

Creazione di API e tipi di Windows

In altre parole, producendo API e tipi. Ad esempio, la produzione dei tipi di API descritte nella sezione precedente; o le API grafiche; le API di archiviazione e file system; le API di rete e così via. Per ulteriori informazioni, vedi API dell'autore con C++/WinRT.

La creazione di API con C++/WinRT è un po' più complessa rispetto a consumarle, perché è necessario usare IDL per definire la struttura dell'API prima di poterla implementare. È disponibile una procedura dettagliata per eseguire questa operazione nei controlli XAML ; associa una proprietà C++/WinRT.

Applicazioni XAML

Questo scenario riguarda la creazione di applicazioni e controlli nel framework dell'interfaccia utente XAML. Lavorare in un'applicazione XAML equivale a una combinazione di utilizzo e creazione. Tuttavia, poiché XAML è il framework dell'interfaccia utente dominante in Windows, e la sua influenza su Windows Runtime è proporzionale a questo, merita la propria categoria di scenario.

Ricordare che XAML funziona meglio con i linguaggi di programmazione che offrono riflessione. In C++/WinRT, a volte devi eseguire un piccolo lavoro aggiuntivo per interagire con il framework XAML. Tutti questi casi sono trattati nella documentazione. I punti di partenza sono controlli XAML; associare a una proprietà C++/WinRT e controlli XAML personalizzati (basati su modelli) con C++/WinRT.

App di esempio scritte in C++/WinRT

Vedi Dove è possibile trovare app di esempio C++/WinRT?.

API importanti