Uso dell'API di hosting XAML WinRT in un'app desktop C++ (Win32)

Importante

Questo argomento usa o menziona tipi del repository GitHub CommunityToolkit/Microsoft.Toolkit.Win32. Per informazioni importanti sul supporto per le isole XAML, vedere l'avviso sulle isole XAML nel repository citato.

A partire da Windows 10, versione 1903, le app desktop non UWP (incluse le app desktop C++ (Win32), WPF e Windows Forms) possono usare l'API di hosting WinRT XAML per ospitare i controlli XAML WinRT in qualsiasi elemento dell'interfaccia utente associato a un handle di finestra. Questa API consente alle app desktop non UWP di usare le funzionalità più recenti dell'interfaccia utente di Windows disponibili solo tramite i controlli XAML WinRT. Le app desktop non UWP, ad esempio, possono usare questa API per ospitare i controlli XAML WinRT che usano Fluent Design System e supportano Windows Ink.

L'API di hosting XAML WinRT offre la base per un set più ampio di controlli che consentono agli sviluppatori di applicare l'interfaccia utente Fluent alle app desktop non UWP. Questa funzionalità è nota come isole XAML. Per una panoramica di questa funzionalità, vedere Ospitare controlli XAML WinRT nelle app desktop (isole XAML).

Nota

Se hai raccolto feedback sulle isole XAML, crea un nuovo problema nel repository Microsoft.Toolkit.Win32 e inserisci i tuoi commenti.

L'API di hosting XAML WinRT è la scelta giusta per l'app desktop?

L'API di hosting XAML WinRT fornisce l'infrastruttura di base per l'hosting di controlli XAML WinRT nelle app desktop. Alcuni tipi di app desktop possono raggiungere questo obiettivo usando API alternative e più convenienti.

  • Se si ha un'app desktop C++ e si vogliono ospitare i controlli XAML WinRT nell'app, è necessario usare l'API di hosting XAML WinRT. Non esistono alternative per questi tipi di app.

  • Per le app WPF e Windows Forms, è consigliabile usare i controlli .NET delle isole XAML nel toolkit della Community Windows invece di usare direttamente l'API di hosting XAML WinRT. Questi controlli usano l'API di hosting XAML WinRT internamente e implementano tutto il comportamento, inclusi lo spostamento tramite tastiera e le modifiche del layout, che altrimenti sarebbe necessario gestire se si usasse l'API direttamente.

Poiché è preferibile che solo le app desktop C++ usino l'API di hosting XAML WinRT, questo articolo fornisce principalmente istruzioni ed esempi per le app desktop C++. Se si preferisce, tuttavia, è possibile usare l'API di hosting XAML WinRT nelle app WPF e Windows Forms. Questo articolo fa riferimento al codice sorgente pertinente per i controlli host per WPF e Windows Forms nel toolkit della Community Windows, permettendo di vedere in che modo i controlli usano l'API di hosting XAML WinRT.

Informazioni su come usare l'API di hosting XAML

Per seguire istruzioni dettagliate con esempi di codice per usare l'API di hosting XAML nelle app desktop C++, vedere questi articoli:

Esempi

Il modo in cui usare l'API di hosting XAML WinRT nel codice dipende dal tipo di app, dalla progettazione dell'app e da altri fattori. Per spiegare come usare questa API nel contesto di un'app completa, questo articolo fa riferimento al codice degli esempi seguenti.

Desktop C++ (Win32)

Gli esempi seguenti illustrano come usare l'API di hosting XAML WinRT in un'app desktop C++:

  • Esempio di isola XAML semplice. Questo esempio illustra un'implementazione di base dell'hosting di un controllo XAML WinRT in un'app desktop C++ non inclusa in un pacchetto.

  • Esempio di isola XAML con controllo personalizzato. Questo esempio illustra un'implementazione completa dell'hosting di un controllo XAML WinRT personalizzato in un'app desktop C++ inclusa in un pacchetto, oltre alla gestione di altri comportamenti, ad esempio l'input da tastiera e lo spostamento dello stato attivo.

WPF e Windows Form

Il controllo WindowsXamlHost nel toolkit della Community Windows è un esempio di riferimento per l'uso dell'API di hosting XAML WinRT nelle app WPF e Windows Forms. È possibile scaricare il codice sorgente dai percorsi seguenti:

Nota

Nelle app WPF e Windows Forms è consigliabile usare i controlli .NET delle isole XAML nel toolkit della Community Windows anziché usare direttamente l'API di hosting XAML WinRT. I collegamenti di esempio WPF e Windows Forms in questo articolo sono solo a scopo illustrativo.

Architettura dell'API

L'API di hosting XAML WinRT include questi tipi di Windows Runtime e interfacce COM principali.

Tipo o interfaccia Descrizione
WindowsXamlManager Questa classe rappresenta il framework XAML UWP. Questa classe fornisce un singolo metodo InitializeForCurrentThread statico che inizializza il framework XAML UWP nel thread corrente nell'app desktop.
DesktopWindowXamlSource Questa classe rappresenta un'istanza del contenuto XAML UWP che stai ospitando nell'app desktop. Il membro più importante di questa classe è la proprietà Content. Assegni questa proprietà a una classe Windows.UI.Xaml.UIElement che vuoi ospitare. Questa classe ha anche altri membri per il routing dello spostamento dello stato attivo della tastiera all'interno e all'esterno delle isole XAML.
IDesktopWindowXamlSourceNative Questa interfaccia COM fornisce il metodo AttachToWindow, che usi per collegare un'isola XAML nell'app a un elemento dell'interfaccia utente padre. Ogni oggetto DesktopWindowXamlSource implementa questa interfaccia.
IDesktopWindowXamlSourceNative2 Questa interfaccia COM fornisce il metodo PreTranslateMessage, che consente al framework XAML UWP di elaborare correttamente determinati messaggi di Windows. Ogni oggetto DesktopWindowXamlSource implementa questa interfaccia.

Il diagramma seguente illustra la gerarchia di oggetti in un'isola XAML ospitata in un'app desktop.

  • Al livello di base si trova l'elemento dell'interfaccia utente dell'app in cui vuoi ospitare l'isola XAML. Questo elemento dell'interfaccia utente deve avere un handle di finestra. Tra gli elementi dell'interfaccia utente in cui è possibile ospitare un'isola XAML sono inclusi, ad esempio, una finestra per le app desktop C++, una classe System.Windows.Interop.HwndHost per le app WPF e una classe System.Windows.Forms.Control per le app Windows Forms.

  • Al livello successivo si trova un oggetto DesktopWindowXamlSource. Questo oggetto fornisce l'infrastruttura per l'hosting dell'isola XAML. Il codice è responsabile della creazione di questo oggetto e del suo collegamento all'elemento padre dell'interfaccia utente.

  • Quando si crea un oggetto DesktopWindowXamlSource, questo oggetto crea automaticamente una finestra figlio nativa per ospitare il controllo XAML WinRT. Questa finestra figlio nativa viene per lo più astratta dal codice, ma puoi accedere all'handle, se necessario.

  • Al livello superiore infine si trova il controllo XAML WinRT da ospitare nell'app desktop. Può essere qualsiasi oggetto UWP derivante da Windows.UI.Xaml.UIElement, inclusi tutti i controlli XAML WinRT forniti in Windows SDK e i controlli utente personalizzati.

DesktopWindowXamlSource architecture

Nota

Quando ospiti le isole XAML in un'app desktop, possono essere in esecuzione più alberi di contenuto XAML nello stesso thread contemporaneamente. Per accedere all'elemento radice di un albero di contenuto XAML in un'isola XAML e ottenere informazioni correlate sul contesto in cui è ospitato, usa la classe XamlRoot. Le API CoreWindow, ApplicationView e Window non forniscono le informazioni corrette per le isole XAML. Per altre informazioni, vedere questa sezione.

Procedure consigliate

Quando si usa l'API di hosting XAML WinRT, seguire queste procedure consigliate per ogni thread che ospita controlli XAML WinRT:

Risoluzione dei problemi

Errore nell'uso dell'API di hosting XAML WinRT in un'app UWP

Problema Risoluzione
L'app riceve un'eccezione COMException con un messaggio simile al seguente: "Non è possibile attivare DesktopWindowXamlSource. Questo tipo non può essere usato in un'app UWP." oppure "Non è possibile attivare WindowsXamlManager". Questo tipo non può essere usato in un'app UWP." Questo errore indica che si sta provando a usare l'API di hosting XAML WinRT (in particolare, che si sta provando a creare un'istanza dei tipi DesktopWindowXamlSource o WindowsXamlManager) in un'app UWP. L'API di hosting XAML WinRT deve essere usata solo per le app desktop non UWP, ad esempio applicazioni WPF, Windows Forms e desktop C++.

Errore durante il tentativo di usare i tipi WindowsXamlManager o DesktopWindowXamlSource

Problema Risoluzione
L'app riceve un'eccezione con un messaggio dimile al seguente: "WindowsXamlManager e DesktopWindowXamlSource sono supportati per le app destinate a Windows versione 10.0.18226.0 e successive. Controllare il manifesto dell'applicazione o il manifesto del pacchetto e verificare che la proprietà MaxTestedVersion sia aggiornata". Questo errore indica che l'applicazione ha provato a usare i tipi WindowsXamlManager o DesktopWindowXamlSource nell'API di hosting XAML WinRT, ma il sistema operativo non può determinare se l'app è stata compilata per Windows 10, versione 1903 o successiva. L'API di hosting XAML WinRT è stata introdotta per la prima volta come anteprima in una versione precedente di Windows 10, ma è supportata solo a partire da Windows 10, versione 1903.

Per risolvere questo problema, crea un pacchetto MSIX per l'app ed eseguila dal pacchetto o installa il pacchetto NuGet Microsoft.Toolkit.Win32.UI.SDK nel progetto.

Errore di collegamento a una finestra in un thread diverso

Problema Risoluzione
L'app riceve un'eccezione COMException con un messaggio simile al seguente: "Metodo AttachToWindow non riuscito perché l'handle di finestra specificato è stato creato in un thread diverso". Questo errore indica che l'applicazione ha chiamato il metodo IDesktopWindowXamlSourceNative::AttachToWindow e gli ha passato l'handle di una finestra creata in un thread diverso. Devi passare a questo metodo l'handle di una finestra creata nello stesso thread del codice da cui stai chiamando il metodo.

Errore di collegamento a una finestra in una finestra di primo livello diversa

Problema Risoluzione
L'app riceve un'eccezione COMException con un messaggio simile al seguente: "Metodo AttachToWindow non riuscito perché l'handle di finestra specificato discende da una finestra di primo livello diversa da quella dell'handle di finestra passato in precedenza ad AttachToWindow nello stesso thread". Questo errore indica che l'applicazione ha chiamato il metodo IDesktopWindowXamlSourceNative::AttachToWindow e gli ha passato l'handle di una finestra che discende da una finestra di primo livello diversa da una finestra specificata in una chiamata precedente a questo metodo nello stesso thread.

Dopo che l'applicazione ha chiamato AttachToWindow in un particolare thread, tutti gli altri oggetti DesktopWindowXamlSource nello stesso thread possono essere collegati solo a finestre discendenti dalla stessa finestra di primo livello passata nella prima chiamata ad AttachToWindow. Quando tutti gli oggetti DesktopWindowXamlSource sono chiusi per un particolare thread, l'oggetto DesktopWindowXamlSource successivo può nuovamente collegarsi a qualsiasi finestra.

Per risolvere questo problema, chiudi tutti gli oggetti DesktopWindowXamlSource associati ad altre finestre di primo livello in questo thread o crea un nuovo thread per questo oggetto DesktopWindowXamlSource.