Verwenden der WinRT-XAML-Hosting-API in einer C++-Desktop (Win32)-App

Wichtig

In diesem Thema werden Typen aus dem GitHub-Repository CommunityToolkit/Microsoft.Toolkit.Win32 verwendet oder erwähnt. Wichtige Informationen zur Unterstützung von XAML Islands finden Sie in diesem Repository im Hinweis zu XAML Islands.

Ab Windows 10, Version 1903, können nicht auf UWP basierende Desktop-Apps (einschließlich C++-Desktop (Win32)-, WPF- und Windows Forms-Apps) die WinRT-XAML-Hosting-API verwenden, um WinRT-XAML-Steuerelemente in beliebigen Elementen der Benutzeroberfläche hosten, die einem Fensterhandle (HWND) zugeordnet sind. Mithilfe dieser API können nicht auf UWP basierende Desktop-Apps die neuesten Features der Windows-Benutzeroberfläche verwenden, die nur in Form von WinRT-XAML-Steuerelementen verfügbar sind. Beispielsweise können nicht auf UWP basierende Desktop-Apps diese API nutzen, um WinRT-XAML-Steuerelemente zu hosten, die das Fluent Design System verwenden und Windows Ink unterstützen.

Die WinRT-XAML-Hosting-API bildet die Grundlage für eine umfassenderen Satz von Steuerelementen, die wir bereitstellen, um Entwicklern die Verwendung der Fluent-Benutzeroberfläche in nicht auf UWP basierenden Desktop-Apps zu ermöglichen. Dieses Feature wird als XAML Islands bezeichnet. Eine Übersicht zu diesem Feature finden Sie unter Hosten von WinRT-XAML-Steuerelementen in Desktop-Apps (XAML Islands).

Hinweis

Wenn Sie Feedback zu XAML Islands haben, erstellen Sie ein neues Thema im Microsoft.Toolkit.Win32-Repository, und geben Sie dort Ihre Kommentare ab.

Ist die WinRT-XAML-Hosting-API die richtige Wahl für Ihre Desktop-App?

Die WinRT-XAML-Hosting-API stellt die Low-Level-Infrastruktur zum Hosten von WinRT-XAML-Steuerelementen in Desktop-Apps bereit. Einige Arten von Desktop-Apps können alternative, komfortablere APIs verwenden, um dieses Ziel zu erreichen.

  • Wenn Sie über eine C++-Desktop-App verfügen und WinRT-XAML-Steuerelemente in Ihrer App hosten möchten, müssen Sie die WinRT-XAML-Hosting-API verwenden. Für diese Art von Apps gibt es keine Alternativen.

  • Für WPF- und Windows Forms-Apps empfehlen wir dringend die Verwendung der XAML Islands .NET-Steuerelemente im Windows Community Toolkit, statt die WinRT-XAML-Hosting-API direkt zu verwenden. Diese Steuerelemente verwenden intern die WinRT-XAML-Hosting-API und implementieren das gesamte Verhalten, einschließlich Tastaturnavigation und Layoutänderungen, um das Sie sich andernfalls, bei direkter Verwendung der WinRT-XAML-Hosting-API, selbst kümmern müssten.

Da wir die Verwendung der WinRT-XAML-Hosting-API nur für C++-Desktop-Apps empfehlen, bietet dieser Artikel in erster Linie Anweisungen und Beispiele für C++-Desktop-Apps. Wenn Sie es wünschen, können Sie die WinRT-XAML-Hosting-API jedoch in WPF- und Windows Forms-Apps verwenden. Dieser Artikel verweist auf den relevanten Quellcode für die Hoststeuerelemente für WPF und Windows Forms im Windows Community Toolkit, damit Sie sehen können, wie die WinRT-XAML-Hosting-API von diesen Steuerelementen verwendet wird.

Die Verwendung der XAML-Hosting-API

Lesen Sie diese Artikel, um den schrittweisen Anweisungen zur Verwendung der XAML-Hosting-API in C++-Desktop-Apps zu folgen:

Beispiele

Die Art und Weise, in der Sie die WinRT-XAML-Hosting-API in Ihrem Code verwenden, hängt vom Typ Ihrer App, dem Entwurf Ihrer App und weiteren Faktoren ab. Um zu veranschaulichen, wie diese API im Kontext einer kompletten App verwendet werden kann, bezieht sich dieser Artikel auf Code aus den folgenden Beispielen.

C++-Desktop (Win32)

In den folgenden Beispielen wird gezeigt, wie die WinRT-XAML-Hosting-API in einer C++-Desktop-App verwendet wird:

WPF und Windows Forms

Das WindowsXamlHost-Steuerelement im Windows-Community-Toolkit dient als Referenzbeispiel zur Verwendung der WinRT-XAML-Hosting-API in WPF- und Windows Forms-Apps. Sie finden den Quellcode an folgenden Speicherorten:

Hinweis

Wir empfehlen dringend, in WPF- und Windows Forms-Apps die XAML Islands .NET-Steuerelemente im Windows-Community-Toolkit zu verwenden, statt die WinRT-XAML-Hosting-API direkt zu verwenden. Die Links zu den WPF- und Windows Forms-Beispielen in diesem Artikel dienen nur der Veranschaulichung.

Architektur der API

Die WinRT-XAML-Hosting-API umfasst diese Windows-Runtime-Haupttypen und -COM-Schnittstellen.

Typ oder Schnittstelle Beschreibung
WindowsXamlManager Diese Klasse stellt das UWP-XAML-Framework dar. Diese Klasse stellt eine einzelne statische InitializeForCurrentThread-Methode bereit, die das UWP XAML-Framework im aktuellen Thread in der Desktop-App initialisiert.
DesktopWindowXamlSource Diese Klasse stellt eine Instanz von UWP-XAML-Inhalt dar, den Sie in Ihrer Desktop-App hosten. Das wichtigste Mitglied dieser Klasse ist die Content-Eigenschaft. Sie weisen diese Eigenschaft einem Windows.UI.Xaml.UIElement zu, das Sie hosten möchten. Diese Klasse weist außerdem andere Elemente zum Routen der Tastaturfokusnavigation in und aus XAML Islands auf.
IDesktopWindowXamlSourceNative Diese COM-Schnittstelle stellt die AttachToWindow-Methode bereit, die Sie verwenden, um ein XAML Island in Ihrer App an ein übergeordnetes Benutzeroberflächenelement anzufügen. Diese Schnittstelle wird von jedem DesktopWindowXamlSource-Objekt implementiert.
IDesktopWindowXamlSourceNative2 Diese COM-Schnittstelle stellt die PreTranslateMessage-Methode bereit, die dem UWP XAML-Framework die ordnungsgemäße Behandlung bestimmter Windows-Nachrichten ermöglicht. Diese Schnittstelle wird von jedem DesktopWindowXamlSource-Objekt implementiert.

Das folgende Diagramm veranschaulicht die Hierarchie der Objekte in einem XAML Island, das in einer Desktop-App gehostet wird.

  • Auf der Basisebene befindet sich das UI-Element Ihrer App, in dem Sie das XAML Island hosten möchten. Dieses UI-Element muss über ein Fensterhandle (HWND) verfügen. Beispiele für Benutzeroberflächenelemente, in denen ein XAML Island gehostet werden kann, sind ein Fenster in C++-Desktop-Apps, ein System.Windows.Interop.HwndHost in WPF-Apps und ein System.Windows.Forms.Control in Windows Forms-Apps.

  • Auf der nächsten Ebene befindet sich ein DesktopWindowXamlSource-Objekt. Dieses Objekt stellt die Infrastruktur zum Hosten des XAML Islands bereit. Ihr Code muss dieses Objekt erstellen und es an das übergeordnete Benutzeroberflächenelement anfügen.

  • Wenn Sie ein DesktopWindowXamlSource erstellen, erstellt dieses Objekt automatisch ein natives untergeordnetes Fenster zum Hosten des WinRT-XAML-Steuerelements. Das native untergeordnete Fenster ist größtenteils von Ihrem Code abstrahiert, Sie können bei Bedarf aber auf sein Handle (HWND) zugreifen.

  • Auf der obersten Ebene befindet sich schließlich das WinRT-XAML-Steuerelement, das Sie in Ihrer Desktop-App hosten möchten. Dabei kann es sich um ein beliebiges UWP-Objekt handeln, das von Windows.UI.Xaml.UIElement abgeleitet ist, einschließlich aller WinRT-XAML-Steuerelemente, die vom Windows SDK bereitgestellt werden, sowie benutzerdefinierter Steuerelemente.

DesktopWindowXamlSource architecture

Hinweis

Wenn Sie XAML Islands in einer Desktop-App hosten, können Sie mehrere Strukturen mit XAML-Inhalten gleichzeitig im selben Thread ausführen. Um auf das Stammelement eine Struktur von XAML-Inhalten in einer XAML Island zuzugreifen und verwandte Informationen über den Kontext abzurufen, in dem dieser gehostet wird, verwenden Sie die Klasse XamlRoot. Die APIs CoreWindow, ApplicationView und Window liefern nicht die richtigen Informationen für XAML Islands. Weitere Informationen finden Sie in diesem Abschnitt.

Bewährte Methoden

Wenn Sie die WinRT-XAML-Hosting-API verwenden, befolgen Sie diese bewährten Methoden für jeden Thread, der WinRT-XAML-Steuerelemente hostet:

  • Erstellen Sie einen dedizierten WindowsXamlManager für den Thread.
  • Erstellen Sie für jedes WinRT-XAML-Steuerelement, das Sie hosten möchten, ein DesktopWindowXamlSource-Steuerelement.
  • Zerstören Sie jedes DesktopWindowXamlSource-Objekt, nachdem es nicht mehr benötigt wird.
  • Zerstören Sie vor dem Beenden des Threads das dedizierte WindowsXamlManager-Objekt für den Thread. Beachten Sie, dass die Zerstörung dieses WindowsXamlManager-Objekts asynchron erfolgt und das Entladen der Windows-Nachrichtenwarteschlange vor dem Beenden des Threads erfordert. Beispiele dafür finden Sie in den XAML Islands-Beispielen.
  • Nach dem Zerstören des WindowsXamlManager-Objekts für einen bestimmten Thread wird das Erstellen eines neuen WindowsXamlManager-Objekts im gleichen Thread nicht unterstützt und führt zu unvorhersehbaren Verhaltensweisen.

Problembehandlung

Fehler beim Verwenden der WinRT-XAML-Hosting-API in einer UWP-App

Problem Lösung
Ihre App empfängt eine COMException mit der folgenden Meldung: „DesktopWindowXamlSource kann nicht aktiviert werden. Dieser Typ kann nicht in einer UWP-App verwendet werden.“ oder „WindowsXamlManager kann nicht aktiviert werden. Dieser Typ kann nicht in einer UWP-App verwendet werden“. Dieser Fehler weist darauf hin, dass Sie versuchen, die WinRT-XAML-Hosting-API in einer UWP-App zu verwenden (insbesondere versuchen Sie, die Typen DesktopWindowXamlSource oder WindowsXamlManager zu instanziieren). Die WinRT-XAML-Hosting-API ist nur zur Verwendung in nicht auf UWP basierenden Desktop-Apps bestimmt, wie etwa WPF-, Windows Forms- und C++-Desktop-Anwendungen.

Fehler beim Versuch, die Typen WindowsXamlManager oder DesktopWindowXamlSource zu verwenden

Problem Lösung
Ihre App empfängt eine Ausnahme mit der folgenden Meldung: „WindowsXamlManager und DesktopWindowXamlSource werden für Apps unterstützt, die auf Windows Version 10.0.18226.0 und höher abzielen. Überprüfen Sie entweder das Anwendungsmanifest oder das Paketmanifest, und vergewissern Sie sich, dass die MaxTestedVersion-Eigenschaft aktualisiert wurde“. Dieser Fehler weist darauf hin, dass Ihre Anwendung versucht hat, die Typen WindowsXamlManager oder DesktopWindowXamlSource in der WinRT-XAML-Hosting-API zu verwenden, das Betriebssystem aber nicht bestimmen kann, ob die App für die Zielplattform Windows 10, Version 1903 oder höher, erstellt wurde. Die WinRT-XAML-Hosting-API wurde zunächst als Vorschauversion in einer früheren Version von Windows 10 vorgestellt, sie wird aber erst ab Windows 10, Version 1903, unterstützt.

Um dieses Problem zu beheben, erstellen Sie entweder ein MSIX-Paket für die App, und führen Sie sie aus diesem Paket aus, oder installieren Sie das NuGet-Paket Microsoft.Toolkit.Win32.UI.SDK in Ihrem Projekt.

Fehler beim Anfügen an ein Fenster in einem anderen Thread

Problem Lösung
Ihre App empfängt eine COMException mit der folgenden Meldung: „Fehler bei der AttachToWindow-Methode, weil das angegebene HWND auf einem anderen Thread erstellt wurde.“ Dieser Fehler weist darauf hin, dass Ihre Anwendung die IDesktopWindowXamlSourceNative::AttachToWindow-Methode aufgerufen und ihr das HWND eines Fensters übergeben hat, das in einem anderen Thread erstellt wurde. Sie müssen dieser Methode das HWND eines Fensters übergeben, das im gleichen Thread wie der Code erstellt wurde, von dem aus Sie die Methode aufrufen.

Fehler beim Anfügen an ein Fenster eines anderen Fensters der obersten Ebene

Problem Lösung
Ihre App empfängt eine COMException mit der folgenden Meldung: „Fehler bei der AttachToWindow-Methode, weil das angegebene HWND von einem anderen Fenster der obersten Ebene stammt als das HWND, das AttachToWindow zuvor im gleichen Thread übergeben wurde“. Dieser Fehler weist darauf hin, dass Ihre Anwendung die IDesktopWindowXamlSourceNative::AttachToWindow-Methode aufgerufen und ihr das HWND eines Fensters übergeben hat, das von einem anderen Fenster der obersten Ebene stammt als ein Fenster, das Sie in einem früheren Aufruf dieser Methode im gleichen Thread angegeben haben.

Nachdem Ihre Anwendung AttachToWindow in einem bestimmten Thread aufgerufen hat, können alle anderen DesktopWindowXamlSource-Objekte im gleichen Thread nur an Fenster angefügt werden, die Nachfolger des gleichen Fensters der obersten Ebene sind, das im ersten Aufruf von AttachToWindow übergeben wurde. Wenn alle DesktopWindowXamlSource-Objekte für einen bestimmten Thread geschlossen sind, kann das nächste DesktopWindowXamlSource wieder an ein beliebiges Fenster angefügt werden.

Um dieses Problem zu beheben, schließen Sie entweder alle DesktopWindowXamlSource-Objekte, die in diesem Thread an andere Fenster der obersten Ebene gebunden sind, oder erstellen Sie einen neuen Thread für dieses DesktopWindowXamlSource.