Héberger un contrôle XAML WinRT personnalisé dans une application de bureau C++ (Win32)

Important

Cette rubrique utilise ou mentionne des types du dépôt GitHub CommunityToolkit/Microsoft.Toolkit.Win32. Pour obtenir des informations importantes sur la prise en charge de XAML Islands, consultez l’avis XAML Islands dans ce dépôt.

Cet article explique comment utiliser l’API d’hébergement XAML WinRT pour héberger un contrôle XAML WinRT personnalisé dans une nouvelle application de bureau C++. Si vous disposez déjà d’un projet d’application de bureau C++, vous pouvez adapter ces étapes et exemples de code à votre projet.

Pour héberger un contrôle XAML WinRT personnalisé, vous allez créer les projets et composants suivants dans le cadre de cette procédure pas à pas :

  • Projet d’application de bureau Windows. Ce projet implémente une application de bureau C++ native. Vous allez ajouter du code à ce projet qui utilise l’API d’hébergement XAML WinRT pour héberger un contrôle XAML WinRT personnalisé.

  • Projet d’application UWP (C++/WinRT) . Ce projet implémente un contrôle XAML WinRT personnalisé. Il implémente également un fournisseur de métadonnées racine pour le chargement de métadonnées pour les types XAML WinRT personnalisés dans le projet.

Conditions requises

  • Visual Studio 2019 version 16.4.3 ou ultérieure.
  • Windows 10, SDK version 1903 (version 10.0.18362) ou ultérieure.
  • Extension Visual Studio C++/WinRT (VSIX) installée avec Visual Studio. C++/WinRT est une projection de langage C++17 moderne entièrement standard pour les API Windows Runtime (WinRT), implémentée en tant que bibliothèque basée sur un fichier d’en-tête et conçue pour vous fournir un accès de première classe à l’API Windows moderne. Pour plus d’informations, consultez C++/WinRT.

Créer un projet d'application de bureau

  1. Dans Visual Studio, créez un projet Application de bureau Windows nommé MyDesktopWin32App. Ce modèle de projet est disponible sous les filtres de projet C++ , Windows et Desktop.

  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de la solution, cliquez sur Recibler la solution, sélectionnez la version 10.0.18362.0 ou une version ultérieure du kit de développement logiciel (SDK), puis cliquez sur OK.

  3. Installez le package NuGet Microsoft.Windows.CppWinRT pour activer la prise en charge de C++/WinRT dans votre projet :

    1. Cliquez avec le bouton droit sur le projet MyDesktopWin32App dans Explorateur de solutions, puis choisissez Gérer les packages NuGet.
    2. Sélectionnez l’onglet Parcourir, recherchez le package Microsoft.Windows.CppWinRT, installez la version la plus récente de ce package.
  4. Dans la fenêtre Gérer les packages NuGet, installez les packages NuGet supplémentaires suivants :

  5. Ajoutez une référence aux métadonnées de Windows Runtime :

    1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud Références de votre projet et sélectionnez Ajouter une référence.
    2. Cliquez sur le bouton Parcourir en bas de la page et accédez au dossier UnionMetadata dans le chemin d’installation du kit SDK. Par défaut, le kit SDK sera installé sur C:\Program Files (x86)\Windows Kits\10\UnionMetadata.
    3. Ensuite, sélectionnez le dossier nommé d’après la version de Windows que vous ciblez (par exemple, 10.0.18362.0) et à l’intérieur de ce dossier, choisissez le fichier Windows.winmd.
    4. Cliquez sur OK pour fermer la boîte de dialogue Ajouter une référence.
  6. Générez la solution et vérifiez qu’elle est correctement générée.

Créer un projet d’application UWP

Ajoutez ensuite un projet d’application UWP (C++/WinRT) à votre solution et apportez des modifications de configuration à ce projet. Plus loin dans cette procédure pas à pas, vous ajouterez du code à ce projet pour implémenter un contrôle XAML WinRT personnalisé et définir une instance de la classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de la solution, puis sélectionnez Ajouter ->Nouveau projet.

  2. Ajoutez un projet Blank App (C++/WinRT) à votre solution. Nommez le projet MyUWPApp et assurez-vous que la version cible et la version minimale sont toutes les deux définies sur Windows 10, version 1903 ou ultérieure.

  3. Installez le package NuGet Microsoft.Toolkit.Win32.UI.XamlApplication dans le projet MyUWPApp. Ce package définit la classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication, que vous utiliserez plus tard dans cette procédure pas à pas.

    1. Cliquez avec le bouton droit sur le projet MyUWPApp et choisissez Gérer les packages NuGet.
    2. Sélectionnez l’onglet Parcourir, recherchez le package Microsoft.Toolkit.Win32.UI.XamlApplication, puis installez la dernière version stable de ce package.
  4. Cliquez avec le bouton droit sur le nœud MyUWPApp et sélectionnez Propriétés. Dans la page Propriétés communes ->C++/WinRT, définissez la propriété Verbosity (Verbosité) sur normal, puis cliquez sur Appliquer. Lorsque vous avez terminé, la page Propriétés devrait ressembler à ceci.

    C++/WinRT project properties

  5. Dans la page Propriétés de configuration ->Général de la fenêtre des propriétés, définissez Type de configuration sur Bibliothèque dynamique (.dll), puis cliquez sur OK pour fermer la fenêtre des propriétés.

    General project properties

  6. Ajoutez un fichier exécutable d’espace réservé au projet MyUWPApp. Ce fichier exécutable d’espace réservé est requis pour permettre à Visual Studio de créer les fichiers projet nécessaires et de générer correctement le projet.

    1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de projet MyUWPApp, puis sélectionnez Ajouter ->Nouvel élément.

    2. Dans la boîte de dialogue Ajouter un nouvel élément, sélectionnez Utilitaire dans la page gauche, puis choisissez Fichier texte (.txt) . Entrez le nom placeholder.exe, puis cliquez sur Ajouter. Add text file

    3. Dans Explorateur de solutions, sélectionnez le fichier placeholder.exe. Dans la fenêtre Propriétés, assurez-vous que la propriété Contenu est définie sur Vrai.

    4. Dans Explorateur de solutions, cliquez avec le bouton droit sur le fichier Package.appxmanifest dans le projet MyUWPApp, sélectionnez Ouvrir avec, choisissez Éditeur XML (Texte) , puis cliquez sur OK.

    5. Recherchez l’élément <Application> et remplacez l’attribut Exécutable par la valeur placeholder.exe. Lorsque vous avez terminé, l'élément <Application> devrait ressembler à ceci.

      <Application Id="App" Executable="placeholder.exe" EntryPoint="MyUWPApp.App">
        <uap:VisualElements DisplayName="MyUWPApp" Description="Project for a single page C++/WinRT Universal Windows Platform (UWP) app with no predefined layout"
          Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" BackgroundColor="transparent">
          <uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png">
          </uap:DefaultTile>
          <uap:SplashScreen Image="Assets\SplashScreen.png" />
        </uap:VisualElements>
      </Application>
      
    6. Enregistrez puis fermez le fichier Package.appxmanifest.

  7. Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud MyUWPApp, puis sélectionnez Décharger le projet.

  8. Cliquez avec le bouton droit sur le nœud MyUWPApp et sélectionnez Modifier MyUWPApp.vcxproj.

  9. Recherchez l’élément <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> et remplacez-le par le code XML suivant. Ce code XML ajoute plusieurs nouvelles propriétés immédiatement avant l’élément.

    <PropertyGroup Label="Globals">
        <WindowsAppContainer>true</WindowsAppContainer>
        <AppxGeneratePriEnabled>true</AppxGeneratePriEnabled>
        <ProjectPriIndexName>App</ProjectPriIndexName>
        <AppxPackage>true</AppxPackage>
    </PropertyGroup>
    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
    
  10. Enregistrez et fermez le fichier projet.

  11. Dans Explorateur de solutions, cliquez avec le bouton droit sur le nœud MyUWPApp, puis sélectionnez Recharger le projet.

Configurer la solution

Dans cette section, vous allez mettre à jour la solution qui contient les deux projets pour configurer les dépendances du projet et les propriétés de génération requises afin que les projets soient correctement créés.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de la solution, puis ajoutez un nouveau fichier XML nommé Solution.props.

  2. Ajoutez le code XML suivant au fichier Solution.props.

    <?xml version="1.0" encoding="utf-8"?>
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      <PropertyGroup>
        <IntDir>$(SolutionDir)\obj\$(Platform)\$(Configuration)\$(MSBuildProjectName)\</IntDir>
        <OutDir>$(SolutionDir)\bin\$(Platform)\$(Configuration)\$(MSBuildProjectName)\</OutDir>
        <GeneratedFilesDir>$(IntDir)Generated Files\</GeneratedFilesDir>
      </PropertyGroup>
    </Project>
    
  3. Dans le menu Affichage, cliquez sur Gestionnaire de propriétés (selon votre configuration, cette option peut apparaître sous Affichage ->Autres fenêtres).

  4. Dans la fenêtre Gestionnaire de propriétés, cliquez avec le bouton droit sur MyDesktopWin32App, puis sélectionnez Ajouter une feuille de propriétés existante. Accédez au fichier Solution.props que vous venez d’ajouter, puis cliquez sur Ouvrir.

  5. Répétez l’étape précédente pour ajouter le fichier Solution.props au projet MyUWPApp dans la fenêtre Gestionnaire de propriétés.

  6. Fermez la fenêtre Gestionnaire de propriétés.

  7. Vérifiez que les modifications apportées à la feuille de propriétés ont été correctement enregistrées. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet MyDesktopWin32App, puis choisissez Propriétés. Cliquez sur Propriétés de configuration ->Général, puis confirmez que les propriétés Répertoire de sortie et Répertoire intermédiaire affichent les valeurs que vous avez ajoutées au fichier Solution.props. Vous pouvez également confirmer les mêmes propriétés pour le projet MyUWPApp. Project properties

  8. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le nœud de la solution, puis choisissez Dépendances du projet. Dans la liste déroulante Projets, vérifiez que l’option MyDesktopWin32App est sélectionnée, puis choisissez MyUWPApp dans la liste Dépend de. Project dependencies

  9. Cliquez sur OK.

Ajouter du code au projet d’application UWP

Vous pouvez maintenant ajouter du code au projet MyUWPApp afin d’effectuer les tâches suivantes :

  • Implémentez un contrôle XAML WinRT personnalisé. Plus loin dans cette procédure pas à pas, vous ajouterez le code qui héberge ce contrôle dans le projet MyDesktopWin32App.
  • Définir un type dérivé de la classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication dans le Kit de ressources Communauté Windows.

Définir un contrôle XAML WinRT personnalisé

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur MyUWPApp, puis sélectionnez Ajouter ->Nouvel élément. Sélectionnez le nœud Visual C++ dans le volet gauche, choisissez Contrôle utilisateur vide (C++/WinRT) , nommez-le MyUserControl, puis cliquez sur Ajouter.

  2. Dans l’éditeur XAML, remplacez le contenu du fichier MyUserControl.xaml par le code XAML suivant, puis enregistrez le fichier.

    <UserControl
        x:Class="MyUWPApp.MyUserControl"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MyUWPApp"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <StackPanel HorizontalAlignment="Center" Spacing="10" 
                    Padding="20" VerticalAlignment="Center">
            <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" 
                           Text="Hello from XAML Islands" FontSize="30" />
            <TextBlock HorizontalAlignment="Center" Margin="15" TextWrapping="Wrap"
                           Text="😍❤💋🌹🎉😎�🐱‍👤" FontSize="16" />
            <Button HorizontalAlignment="Center" 
                    x:Name="Button" Click="ClickHandler">Click Me</Button>
        </StackPanel>
    </UserControl>
    

Définir une classe XamlApplication

Modifiez ensuite la classe App par défaut du projet MyUWPApp afin de la dériver de la classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication fournie par le Kit de ressources Communauté Windows. Cette classe prend en charge l’interface IXamlMetadataProvider, qui permet à votre application de découvrir et de charger des métadonnées pour les contrôles XAML WinRT personnalisés dans les assemblys du répertoire actif de votre application au moment de l’exécution. Cette classe initialise également le framework XAML WinRT pour le thread actuel. Plus loin dans cette procédure pas à pas, vous allez mettre à jour le projet Desktop pour créer une instance de cette classe.

Notes

Chaque solution qui utilise XAML Islands ne peut contenir qu’un seul projet définissant un objet XamlApplication. Tous les contrôles XAML WinRT personnalisés de votre application partagent le même objet XamlApplication.

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le fichier MainPage.xaml dans le projet MyUWPApp. Cliquez sur Retirer puis Supprimer pour supprimer définitivement ce fichier du projet.

  2. Dans le projet MyUWPApp, développez le fichier App.xaml.

  3. Remplacez le contenu des fichiers App.xaml, App.cpp, App.h et App.idl par le code suivant.

    • App.xaml :

      <Toolkit:XamlApplication
          x:Class="MyUWPApp.App"
          xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
          xmlns:local="using:MyUWPApp">
      </Toolkit:XamlApplication>
      
    • App.idl :

      namespace MyUWPApp
      {
           [default_interface]
           runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
           {
              App();
           }
      }
      
    • App.h :

      #pragma once
      #include "App.g.h"
      #include "App.base.h"
      namespace winrt::MyUWPApp::implementation
      {
          class App : public AppT2<App>
          {
          public:
              App();
              ~App();
          };
      }
      namespace winrt::MyUWPApp::factory_implementation
      {
          class App : public AppT<App, implementation::App>
          {
          };
      }
      
    • App.cpp :

      #include "pch.h"
      #include "App.h"
      #include "App.g.cpp"
      using namespace winrt;
      using namespace Windows::UI::Xaml;
      namespace winrt::MyUWPApp::implementation
      {
          App::App()
          {
              Initialize();
              AddRef();
              m_inner.as<::IUnknown>()->Release();
          }
          App::~App()
          {
              Close();
          }
      }
      

      Notes

      L’instruction #include "App.g.cpp" est nécessaire quand la propriété Optimisédans la page Propriétés communes ->C++/WinRT des propriétés de projet est définie sur Oui. Il s’agit de la valeur par défaut pour les nouveaux projets C++/WinRT. Pour plus d’informations sur les effets de la propriété Optimisé, consultez cette section.

  4. Ajoutez un nouveau fichier d’en-tête au projet MyUWPApp nommé app.base.h.

  5. Ajoutez le code suivant au fichier app.base.h, enregistrez le fichier, puis fermez-le.

    #pragma once
    namespace winrt::MyUWPApp::implementation
    {
        template <typename D, typename... I>
        struct App_baseWithProvider : public App_base<D, ::winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider>
        {
            using IXamlType = ::winrt::Windows::UI::Xaml::Markup::IXamlType;
            IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
            {
                return _appProvider.GetXamlType(type);
            }
            IXamlType GetXamlType(::winrt::hstring const& fullName)
            {
                return _appProvider.GetXamlType(fullName);
            }
            ::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
            {
                return _appProvider.GetXmlnsDefinitions();
            }
        private:
            bool _contentLoaded{ false };
            winrt::MyUWPApp::XamlMetaDataProvider _appProvider;
        };
        template <typename D, typename... I>
        using AppT2 = App_baseWithProvider<D, I...>;
    }
    
  6. Générez la solution et vérifiez qu’elle est correctement générée.

Configurer le projet de bureau pour utiliser des types de contrôles personnalisés

Pour que l’application MyDesktopWin32App puisse héberger un contrôle XAML WinRT personnalisé dans un îlot XAML, l’application doit être configurée pour utiliser des types de contrôles personnalisés provenant du projet MyUWPApp. Il existe deux façons de procéder, et vous pouvez choisir l’une ou l’autre de ces deux options à mesure que vous effectuez cette procédure pas à pas.

Option 1 : Empaqueter l’application à l’aide de MSIX

Vous pouvez empaqueter l’application dans un package MSIX en vue du déploiement. MSIX est une technologie d’empaquetage moderne pour Windows, basée sur une combinaison des technologies d’installation MSI, .appx, App-V et ClickOnce.

  1. Ajoutez un nouveau projet d’empaquetage d’application Windows à votre solution. À mesure que vous créez le projet, nommez-le MyDesktopWin32Project et sélectionnez Windows 10, version 1903 (10.0 ; Build 18362) à la fois pour la version cible et la version minimale.

  2. Dans le projet d’empaquetage, cliquez avec le bouton droit sur le nœud Applications, puis choisissez Ajouter une référence. Dans la liste des projets, activez la case à cocher en regard du projet MyDesktopWin32App, puis cliquez sur OK. Reference project

  3. Pour plus d’informations sur la distribution/le déploiement du package, consultez Gérer votre déploiement MSIX.

Notes

Si vous choisissez de ne pas inclure votre application dans un package MSIX pour le déploiement, Visual C++ Runtime doit alors être installé sur les ordinateurs qui exécutent votre application.

Option 2 : Créer un manifeste d'application

Vous pouvez ajouter un manifeste d’application à votre application.

  1. Cliquez avec le bouton droit sur le projet MyDesktopWin32App, puis sélectionnez Ajouter ->Nouvel élément.

  2. Dans la boîte de dialogue Ajouter un nouvel élément, cliquez sur Web dans le volet gauche, puis sélectionnez Fichier XML (.xml) .

  3. Nommez le nouveau fichier app.manifest, puis cliquez sur Ajouter.

  4. Remplacez le contenu du nouveau fichier par le code XML ci-dessous. Ce code XML inscrit les types de contrôles personnalisés dans le projet MyUWPApp.

    <?xml version="1.0" encoding="utf-8"?>
    <assembly
     xmlns="urn:schemas-microsoft-com:asm.v1"
     xmlns:asmv3="urn:schemas-microsoft-com:asm.v3"
     manifestVersion="1.0">
      <asmv3:file name="MyUWPApp.dll">
        <activatableClass
            name="MyUWPApp.App"
            threadingModel="both"
            xmlns="urn:schemas-microsoft-com:winrt.v1" />
        <activatableClass
            name="MyUWPApp.XamlMetadataProvider"
            threadingModel="both"
            xmlns="urn:schemas-microsoft-com:winrt.v1" />
        <activatableClass
            name="MyUWPApp.MyUserControl"
            threadingModel="both"
            xmlns="urn:schemas-microsoft-com:winrt.v1" />
      </asmv3:file>
    </assembly>
    

Configurer d’autres propriétés de projet de bureau

Mettez à jour le projet MyDesktopWin32App afin de définir une macro pour des répertoires Include supplémentaires et de configurer d’autres propriétés.

  1. Dans Explorateur de solutions, cliquez avec le bouton droit sur le projet MyDesktopWin32App, puis choisissez Décharger le projet.

  2. Cliquez avec le bouton droit sur MyDesktopWin32App (déchargé) , puis sélectionnez Modifier MyDesktopWin32App.vcxproj.

  3. Ajoutez le code XML suivant juste avant la balise de fermeture </Project> à la fin du fichier. Enregistrez et fermez le fichier.

      <!-- Configure these for your UWP project -->
      <PropertyGroup>
        <AppProjectName>MyUWPApp</AppProjectName>
      </PropertyGroup>
      <PropertyGroup>
        <AppIncludeDirectories>$(SolutionDir)\obj\$(Platform)\$(Configuration)\$(AppProjectName)\;$(SolutionDir)\obj\$(Platform)\$(Configuration)\$(AppProjectName)\Generated Files\;</AppIncludeDirectories>
      </PropertyGroup>
      <ItemGroup>
        <ProjectReference Include="..\$(AppProjectName)\$(AppProjectName).vcxproj" />
      </ItemGroup>
      <!-- End Section-->
    
  4. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur MyDesktopWin32App (déchargé) , puis sélectionnez Recharger le projet.

  5. Cliquez avec le bouton droit sur le projet MyDesktopWin32App, sélectionnez Propriétés, puis développez Outil Manifeste ->Entrée et sortie dans le volet gauche. Définissez la propriété Prise en charge DPI sur Reconnaissant les résolutions élevées par moniteur. Si vous ne définissez pas cette propriété, vous risquez de rencontrer une erreur de configuration de manifeste dans certains scénarios impliquant des résolutions élevées.

    Screenshot of the C/C++ project settings.

  6. Cliquez sur OK pour fermer la boîte de dialogue Pages de propriétés.

Héberger le contrôle XAML WinRT personnalisé dans le projet de bureau

Vous êtes enfin prêt à ajouter du code au projet MyDesktopWin32App pour héberger le contrôle XAML WinRT personnalisé que vous avez défini précédemment dans le projet MyUWPApp.

  1. Dans le projet MyDesktopWin32App, ouvrez le fichier framework.h et commentez la ligne de code suivante. Enregistrez le fichier une fois que vous avez terminé.

    #define WIN32_LEAN_AND_MEAN
    
  2. Ouvrez le fichier MyDesktopWin32App.h et remplacez le contenu de ce fichier par le code suivant pour référencer les fichiers d’en-tête C++/WinRT requis. Enregistrez le fichier une fois que vous avez terminé.

    #pragma once
    
    #include "resource.h"
    #include <winrt/Windows.Foundation.Collections.h>
    #include <winrt/Windows.system.h>
    #include <winrt/windows.ui.xaml.hosting.h>
    #include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
    #include <winrt/windows.ui.xaml.controls.h>
    #include <winrt/Windows.ui.xaml.media.h>
    #include <winrt/Windows.UI.Core.h>
    #include <winrt/MyUWPApp.h>
    
    using namespace winrt;
    using namespace Windows::UI;
    using namespace Windows::UI::Composition;
    using namespace Windows::UI::Xaml::Hosting;
    using namespace Windows::Foundation::Numerics;
    using namespace Windows::UI::Xaml::Controls;
    
  3. Ouvrez le fichier MyDesktopWin32App.cpp et ajoutez le code suivant à la section Global Variables:.

    winrt::MyUWPApp::App hostApp{ nullptr };
    winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _desktopWindowXamlSource{ nullptr };
    winrt::MyUWPApp::MyUserControl _myUserControl{ nullptr };
    
  4. Dans le même fichier, ajoutez le code suivant à la section Forward declarations of functions included in this code module:.

    void AdjustLayout(HWND);
    
  5. Dans le même fichier, ajoutez le code suivant immédiatement après le commentaire TODO: Place code here. dans la fonction wWinMain.

    // TODO: Place code here.
    winrt::init_apartment(winrt::apartment_type::single_threaded);
    hostApp = winrt::MyUWPApp::App{};
    _desktopWindowXamlSource = winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource{};
    
  6. Dans le même fichier, remplacez la fonction InitInstance par défaut par le code suivant.

    BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
    {
        hInst = hInstance; // Store instance handle in our global variable
    
        HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
    
        if (!hWnd)
        {
            return FALSE;
        }
    
        // Begin XAML Islands walkthrough code.
        if (_desktopWindowXamlSource != nullptr)
        {
            auto interop = _desktopWindowXamlSource.as<IDesktopWindowXamlSourceNative>();
            check_hresult(interop->AttachToWindow(hWnd));
            HWND hWndXamlIsland = nullptr;
            interop->get_WindowHandle(&hWndXamlIsland);
            RECT windowRect;
            ::GetWindowRect(hWnd, &windowRect);
            ::SetWindowPos(hWndXamlIsland, NULL, 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_SHOWWINDOW);
            _myUserControl = winrt::MyUWPApp::MyUserControl();
            _desktopWindowXamlSource.Content(_myUserControl);
        }
        // End XAML Islands walkthrough code.
    
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
    
        return TRUE;
    }
    
  7. Dans le même fichier, ajoutez la nouvelle fonction suivante à la fin du fichier.

    void AdjustLayout(HWND hWnd)
    {
        if (_desktopWindowXamlSource != nullptr)
        {
            auto interop = _desktopWindowXamlSource.as<IDesktopWindowXamlSourceNative>();
            HWND xamlHostHwnd = NULL;
            check_hresult(interop->get_WindowHandle(&xamlHostHwnd));
            RECT windowRect;
            ::GetWindowRect(hWnd, &windowRect);
            ::SetWindowPos(xamlHostHwnd, NULL, 0, 0, windowRect.right - windowRect.left, windowRect.bottom - windowRect.top, SWP_SHOWWINDOW);
        }
    }
    
  8. Dans le même fichier, recherchez la fonction WndProc. Remplacez le gestionnaire WM_DESTROY par défaut dans l’instruction switch par le code suivant.

    case WM_DESTROY:
        PostQuitMessage(0);
        if (_desktopWindowXamlSource != nullptr)
        {
            _desktopWindowXamlSource.Close();
            _desktopWindowXamlSource = nullptr;
        }
        break;
    case WM_SIZE:
        AdjustLayout(hWnd);
        break;
    
  9. Enregistrez le fichier.

  10. Générez la solution et vérifiez qu’elle est correctement générée.

Ajouter un contrôle de la bibliothèque WinUI 2 au contrôle personnalisé

Traditionnellement, les contrôles XAML WinRT ont été publiés dans le cadre du système d’exploitation Windows et mis à la disposition des développeurs via le SDK Windows. La bibliothèque WinUI est une autre approche, dans laquelle les versions mises à jour des contrôles XAML WinRT du SDK Windows sont distribuées dans un package NuGet qui n’est pas lié aux versions de SDK Windows. Cette bibliothèque comprend également de nouveaux contrôles qui ne font pas partie du SDK Windows et de la plateforme UWP par défaut.

Cette section montre comment ajouter un contrôle XAML WinRT de la bibliothèque WinUI 2 à votre contrôle utilisateur.

Notes

XAML Islands prend uniquement en charge l’hébergement des contrôles issus de la bibliothèque WinUI 2. La prise en charge de l’hébergement des contrôles de la bibliothèque WinUI 3 sera disponible dans une version ultérieure.

  1. Dans le projet MyUWPApp, installez la dernière version ou la dernière version préliminaire du package NuGet Microsoft.UI.Xaml.

    • Si vous avez choisi d’empaqueter le projet MyDesktopWin32App à l’aide de MSIX précédemment dans cette procédure, vous pouvez installer la préversion ou la version finale du package NuGet Microsoft.UI.Xaml. Les applications de bureau empaquetées peuvent utiliser la préversion ou la version finale de ce package.
    • Si vous avez choisi de ne pas empaqueter le projet MyDesktopWin32App, vous devez installer la préversion du package NuGet Microsoft.UI.Xaml. Les applications de bureau non empaquetées doivent utiliser la préversion de ce package.
  2. Dans le fichier pch.h de ce projet, ajoutez les instructions #include suivantes et enregistrez vos modifications. Ces instructions apportent un ensemble obligatoire d’en-têtes de projection depuis la bibliothèque WinUI vers votre projet. Cette étape est requise pour tout projet C++/WinRT qui utilise la bibliothèque WinUI. Pour plus d’informations, consultez cet article.

    #include "winrt/Microsoft.UI.Xaml.Automation.Peers.h"
    #include "winrt/Microsoft.UI.Xaml.Controls.Primitives.h"
    #include "winrt/Microsoft.UI.Xaml.Media.h"
    #include "winrt/Microsoft.UI.Xaml.XamlTypeInfo.h"
    
  3. Dans le fichier App.xaml du même projet, ajoutez l’élément enfant suivant à l’élément <xaml:XamlApplication> et enregistrez vos modifications.

    <Application.Resources>
        <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
    </Application.Resources>
    

    Après avoir ajouté cet élément, le contenu de ce fichier devrait maintenant ressembler à ce qui suit.

    <Toolkit:XamlApplication
        x:Class="MyUWPApp.App"
        xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:MyUWPApp">
        <Application.Resources>
            <XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls"/>
        </Application.Resources>
    </Toolkit:XamlApplication>
    
  4. Dans le même projet, ouvrez le fichier MyUserControl.xaml, puis ajoutez la déclaration d’espace de noms suivante à l’élément <UserControl>.

    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    
  5. Dans le même fichier, ajoutez un élément <winui:RatingControl /> en tant qu’enfant de l’élément <StackPanel> et enregistrez vos modifications. Cet élément ajoute une instance de la classe RatingControl issue de la bibliothèque WinUI. Après avoir ajouté cet élément, l’élément <StackPanel> devrait maintenant ressembler à ce qui suit.

    <StackPanel HorizontalAlignment="Center" Spacing="10" 
                Padding="20" VerticalAlignment="Center">
        <TextBlock HorizontalAlignment="Center" TextWrapping="Wrap" 
                       Text="Hello from XAML Islands" FontSize="30" />
        <TextBlock HorizontalAlignment="Center" Margin="15" TextWrapping="Wrap"
                       Text="😍❤💋🌹🎉😎�🐱‍👤" FontSize="16" />
        <Button HorizontalAlignment="Center" 
                x:Name="Button" Click="ClickHandler">Click Me</Button>
        <winui:RatingControl />
    </StackPanel>
    
  6. Générez la solution et vérifiez qu’elle est correctement générée.

Tester l'application

Exécutez la solution et vérifiez que MyDesktopWin32App s’ouvre dans la fenêtre suivante.

MyDesktopWin32App app

Étapes suivantes

De nombreuses applications de bureau qui hébergent XAML Islands doivent gérer des scénarios supplémentaires pour offrir une expérience utilisateur fluide. Par exemple, des applications de bureau peuvent devoir gérer la saisie au clavier dans des îlots XAML, la navigation en mode focus entre les îlots XAML et d’autres éléments d’interface utilisateur, et des changements de disposition.

Pour plus d’informations sur la gestion de ces scénarios et pour obtenir des exemples de code connexes, consultez Scénarios avancés pour XAML Islands dans les applications de bureau C++.