Ospitare un controllo XAML WinRT personalizzato 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.

Questo articolo illustra come usare l'API di hosting XAML WinRT per ospitare un controllo XAML WinRT personalizzato in una nuova app desktop C++. Se si dispone di un progetto di app desktop C++ esistente, è possibile adattare questi passaggi ed esempi di codice per il proprio progetto.

Per ospitare un controllo XAML WinRT personalizzato, si creeranno i progetti e i componenti seguenti come parte di questa procedura dettagliata:

  • Progetto Applicazione desktop di Windows. Questo progetto implementa un'app desktop C++ nativa. A questo progetto si aggiungerà codice che usa l'API di hosting XAML WinRT per ospitare un controllo XAML WinRT personalizzato.

  • Progetto di app UWP (C++/WinRT). Questo progetto implementa un controllo XAML WinRT personalizzato. Implementa inoltre un provider di metadati radice per il caricamento dei metadati per i tipi XAML WinRT personalizzati nel progetto.

Requisiti

  • Visual Studio 2019 versione 16.4.3 o successiva.
  • Windows 10, versione 1903 SDK (versione 10.0.18362) o successiva.
  • Estensione di Visual Studio C++/WinRT (VSIX) installata con Visual Studio. C++/WinRT è una proiezione del linguaggio C++ 17 interamente standard e moderna per le API di Windows Runtime (WinRT), implementata come libreria basata su file di intestazione e progettata per fornirti accesso privilegiato alla moderna API di Windows. Per altre informazioni, vedi C++/WinRT.

Creare un progetto di applicazione desktop

  1. In Visual Studio crea un nuovo progetto Applicazione desktop Windows denominato MyDesktopWin32App. Questo modello di progetto è disponibile nei filtri di progetto C++, Windows e Desktop.

  2. In Esplora soluzioni fai clic con il pulsante destro del mouse sul nodo della soluzione, scegli Ridestina soluzione, seleziona la versione 10.0.18362.0 o una versione più recente dell'SDK e quindi fai clic su OK.

  3. Installa il pacchetto NuGet Microsoft.Windows.CppWinRT per abilitare il supporto per C++/WinRT nel progetto:

    1. Fai clic con il pulsante destro del mouse sul progetto MyDesktopWin32App in Esplora soluzioni e scegli Gestisci pacchetti NuGet.
    2. Seleziona la scheda Sfoglia, cerca il pacchetto Microsoft.Windows.CppWinRT e installa la versione più recente del pacchetto.
  4. Nella finestra Gestisci pacchetti NuGet, installa i pacchetti NuGet aggiuntivi seguenti:

  5. Aggiungere un riferimento ai metadati di Windows Runtime:

    1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo Riferimenti del progetto e scegliere Aggiungi riferimento.
    2. Fare clic sul pulsante Sfoglia nella parte inferiore della pagina e passare alla cartella UnionMetadata nel percorso di installazione dell'SDK. Per impostazione predefinita, l'SDK verrà installato in C:\Program Files (x86)\Windows Kits\10\UnionMetadata.
    3. Selezionare quindi la cartella denominata con la versione di Windows destinazione (ad esempio 10.0.18362.0) e all'interno di questa selezionare il file Windows.winmd.
    4. Scegliere OK per chiudere la finestra di dialogo Aggiungi riferimento.
  6. Compila la soluzione e verifica che venga compilata correttamente.

Creare un progetto di app UWP

A questo punto, aggiungi un progetto di app UWP (C++/WinRT) alla soluzione e apporta alcune modifiche alla configurazione del progetto. Più avanti in questa procedura dettagliata si aggiungerà codice a questo progetto per implementare un controllo XAML WinRT personalizzato e si definirà un'istanza della classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication.

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo della soluzione e scegliere Aggiungi ->Nuovo progetto.

  2. Aggiungi un progetto App vuota (C++/WinRT) alla soluzione. Assegna il nome MyUWPApp al progetto e verifica che la versione di destinazione e la versione minima siano entrambe impostate su Windows 10, versione 1903 o successiva.

  3. Installa il pacchetto NuGet Microsoft.Toolkit.Win32.UI.XamlApplication nel progetto MyUWPApp. Questo pacchetto definisce la classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication, che userai più avanti in questa procedura dettagliata.

    1. Fai clic con il pulsante destro del mouse sul progetto MyUWPApp e scegli Gestisci pacchetti NuGet.
    2. Selezionare la scheda Sfoglia, cercare il pacchetto Microsoft.Toolkit.Win32.UI.XamlApplication e installare la versione stabile più recente del pacchetto.
  4. Fai clic con il pulsante destro del mouse sul nodo MyUWPApp e scegli Proprietà. Nella pagina Proprietà comuni ->C++/WinRT impostare la proprietà Verbosity su normal e quindi fare clic su Applica. Al termine, la pagina delle proprietà avrà un aspetto simile al seguente.

    C++/WinRT project properties

  5. Nella pagina Proprietà di configurazione ->Generale della finestra delle proprietà impostare Tipo di configurazione su Libreria dinamica (.dll) e quindi scegliere OK per chiudere la finestra delle proprietà.

    General project properties

  6. Aggiungi un file eseguibile segnaposto al progetto MyUWPApp. Questo file è necessario per consentire a Visual Studio di generare i file di progetto richiesti e compilare il progetto correttamente.

    1. In Esplora soluzioni fare clic con il pulsante destro del mouse sul nodo del progetto MyUWPApp e scegliere Aggiungi ->Nuovo elemento.

    2. Nella finestra di dialogo Aggiungi nuovo elemento seleziona Utilità nella pagina a sinistra e quindi seleziona File di testo (.txt). Immetti il nome placeholder.exe e fai clic su Aggiungi. Add text file

    3. In Esplora soluzioni seleziona il file placeholder.exe. Nella finestra Proprietà verifica che la proprietà Contenuto sia impostata su True.

    4. In Esplora soluzioni fai clic con il pulsante destro del mouse sul file Package.appxmanifest nel progetto MyUWPApp, scegli Apri con, quindi Editor XML (testo) e infine fai clic su OK.

    5. Trova l'elemento <Application> e modifica il valore dell'attributo Executable in placeholder.exe. Al termine, l'elemento <Application> dovrebbe avere un aspetto simile al seguente.

      <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. Salva e chiudi il file Package.appxmanifest.

  7. In Esplora soluzioni fai clic con il pulsante destro del mouse sul nodo MyUWPApp e scegli Scarica progetto.

  8. Fai clic con il pulsante destro del mouse sul nodo MyUWPApp e scegli Modifica MyUWPApp.vcxproj.

  9. Trova l'elemento <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> e sostituiscilo con il codice XML seguente. Questo codice XML aggiunge alcune nuove proprietà immediatamente prima dell'elemento.

    <PropertyGroup Label="Globals">
        <WindowsAppContainer>true</WindowsAppContainer>
        <AppxGeneratePriEnabled>true</AppxGeneratePriEnabled>
        <ProjectPriIndexName>App</ProjectPriIndexName>
        <AppxPackage>true</AppxPackage>
    </PropertyGroup>
    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
    
  10. Salva e chiudi il file di progetto.

  11. In Esplora soluzioni fai clic con il pulsante destro del mouse sul nodo MyUWPApp e scegli Ricarica progetto.

Configurare la soluzione

In questa sezione aggiornerai la soluzione che contiene entrambi i progetti per configurare le dipendenze tra i progetti e le proprietà necessarie per la corretta compilazione dei progetti.

  1. In Esplora soluzioni fai clic con il pulsante destro del mouse sul nodo della soluzione e aggiungi un nuovo file XML denominato Solution.props.

  2. Aggiungi il codice XML seguente al file 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. Nel menu Visualizza fare clic su Gestione proprietà. A seconda della configurazione, potrebbe trovarsi in Visualizza ->Altre finestre.

  4. Nella finestra Gestione proprietà fai clic con il pulsante destro del mouse su MyDesktopWin32App e scegli Aggiungi finestra delle proprietà esistente. Passa al file Solution.props appena aggiunto e fai clic su Apri.

  5. Ripeti il passaggio precedente per aggiungere il file Solution.props al progetto MyUWPApp nella finestra Gestione proprietà.

  6. Chiudi la finestra Gestione proprietà.

  7. Verifica che le modifiche apportate alla finestra delle proprietà siano state salvate correttamente. In Esplora soluzioni fai clic con il pulsante destro del mouse sul progetto MyDesktopWin32App e scegli Proprietà. Fare clic su Proprietà di configurazione ->Generale e verificare che le proprietà Directory di output e Directory intermedia includano i valori aggiunti al file Solution.props. Puoi anche eseguire la stessa verifica per il progetto MyUWPApp. Project properties

  8. In Esplora soluzioni fai clic con il pulsante destro del mouse sul nodo della soluzione e scegli Dipendenze progetto. Nell'elenco a discesa Progetti verifica che sia selezionato il progetto MyDesktopWin32App e seleziona MyUWPApp nell'elenco Dipendente da. Project dependencies

  9. Fare clic su OK.

Aggiungere codice al progetto di app UWP

A questo punto puoi aggiungere codice al progetto MyUWPApp per eseguire queste attività:

  • Implementare un controllo XAML WinRT personalizzato. Più avanti in questa procedura dettagliata aggiungerai il codice che ospita questo controllo nel progetto MyDesktopWin32App.
  • Definisci un tipo che deriva dalla classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication in Windows Community Toolkit.

Definire un controllo XAML WinRT personalizzato

  1. In Esplora soluzioni fare clic con il pulsante destro del mouse su MyUWPApp e scegliere Aggiungi ->Nuovo elemento. Seleziona il nodo Visual C++ nel riquadro a sinistra, seleziona Controllo utente vuoto (C++/WinRT), assegna il nome MyUserControl e quindi fai clic su Aggiungi.

  2. Nell'editor XAML sostituisci il contenuto del file MyUserControl.xaml con il codice XAML seguente e quindi salva il file.

    <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>
    

Definire una classe XamlApplication

A questo punto, aggiorna la classe App predefinita nel progetto MyUWPApp in modo che derivi dalla classe Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication fornita da Windows Community Toolkit. Questa classe supporta l'interfaccia IXamlMetadataProvider, che consente all'app di individuare e caricare i metadati dei controlli XAML WinRT personalizzati negli assembly nella directory corrente dall'applicazione in fase di esecuzione. La classe inizializza anche il framework XAML WinRT per il thread corrente. Più avanti in questa procedura dettagliata aggiornerai il progetto desktop per creare un'istanza di questa classe.

Nota

Ogni soluzione che usa le isole XAML può contenere un solo progetto che definisce un oggetto XamlApplication. Tutti i controlli XAML WinRT personalizzati nell'app condividono lo stesso oggetto XamlApplication.

  1. In Esplora soluzioni fai clic con il pulsante destro del mouse sul file MainPage.xaml nel progetto MyUWPApp. Fare clic su Rimuovi e quindi su Elimina per eliminare definitivamente il file dal progetto.

  2. Nel progetto MyUWPApp espandi file App.xaml.

  3. Sostituisci il contenuto dei file App.xaml, App.cpp, App.h e App.idl con il codice seguente.

    • 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();
          }
      }
      

      Nota

      L'istruzione #include "App.g.cpp" è necessaria quando la proprietà Optimized nella pagina Proprietà comuni ->C++/WinRT delle proprietà del progetto è impostata su . Si tratta dell'impostazione predefinita per i nuovi progetti C++/WinRT. Per altre informazioni sugli effetti della proprietà Optimized, vedere questa sezione.

  4. Aggiungi un nuovo file di intestazione al progetto MyUWPApp denominato app.base.h.

  5. Aggiungi il codice seguente al file app.base.h, salva il file e chiudilo.

    #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. Compila la soluzione e verifica che venga compilata correttamente.

Configurare il progetto desktop per l'utilizzo di tipi di controllo personalizzati

Prima che l'app MyDesktopWin32App possa ospitare un controllo XAML WinRT personalizzato in un'isola XAML, è necessario configurarlo in modo che utilizzi tipi di controllo personalizzati del progetto MyUWPApp. Esistono due modi per eseguire questa operazione e puoi scegliere una delle due opzioni per completare questa procedura dettagliata.

Opzione 1: Creare un pacchetto dell'app usando MSIX

Puoi creare un pacchetto MSIX dell'app per la distribuzione. MSIX è la moderna tecnologia per la creazione di pacchetti di app per Windows ed è basata su una combinazione delle tecnologie di installazione MSI, .appx, App-V e ClickOnce.

  1. Aggiungi un nuovo progetto alla soluzione usando Progetto di creazione pacchetti per applicazioni Windows. Quando crei il progetto, assegna il nome MyDesktopWin32Project e seleziona Windows 10, versione 1903 (10.0; build 18362) per Versione di destinazione e Versione minima.

  2. Nel progetto di creazione del pacchetto fai clic con il pulsante destro del mouse sul nodo Applicazioni e scegli Aggiungi riferimento. Nell'elenco dei progetti seleziona la casella di controllo accanto al progetto MyDesktopWin32App e fai clic su OK. Reference project

  3. Per informazioni sulla distribuzione del pacchetto, vedere Gestire la distribuzione MSIX.

Nota

Scegliendo di non creare un pacchetto MSIX dell'applicazione per la distribuzione, nei computer che eseguono l'app deve essere installato il runtime di Visual C++.

Opzione 2: Creare un manifesto dell'applicazione

Puoi aggiungere un manifesto dell'applicazione all'app.

  1. Fare clic con il pulsante destro del mouse sul progetto MyDesktopWin32App e scegliere Aggiungi ->Nuovo elemento.

  2. Nella finestra di dialogo Aggiungi nuovo elemento fai clic su Web nel riquadro a sinistra e seleziona File XML (.xml).

  3. Assegna il nome app.manifest al nuovo file e fai clic su Aggiungi.

  4. Sostituisci il contenuto del nuovo file con il codice XML seguente. Questo codice XML registra i tipi di controllo personalizzati nel progetto 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>
    

Configurare proprietà aggiuntive per il progetto desktop

Aggiorna quindi il progetto MyDesktopWin32App per definire una macro per altre directory di inclusione e configurare proprietà aggiuntive.

  1. In Esplora soluzioni fai clic con il pulsante destro del mouse sul progetto MyDesktopWin32App e scegli Scarica progetto.

  2. Fai clic con il pulsante destro del mouse su MyDesktopWin32App (Scaricato) e scegli Modifica MyDesktopWin32App.vcxproj.

  3. Aggiungi il codice XML seguente appena prima del tag </Project> di chiusura alla fine del file. Salva e chiudi il file.

      <!-- 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. In Esplora soluzioni fare clic con il pulsante destro del mouse su MyDesktopWin32App (Scaricato) e scegliere Ricarica progetto.

  5. Fare clic con il pulsante destro del mouse sul progetto MyDesktopWin32App, selezionare Proprietà e quindi espandere Strumento Manifesto ->Input e Output nel riquadro sinistro. Imposta la proprietà Compatibilità con DPI su Per monitor compatibilità DPI avanzata. Se non imposti questa proprietà, è possibile che si verifichi un errore di configurazione del manifesto in determinati scenari con valori DPI elevati.

    Screenshot of the C/C++ project settings.

  6. Fare clic su OK per chiudere la finestra di dialogo Pagine delle proprietà.

Ospitare il controllo XAML WinRT personalizzato nel progetto desktop

È infine possibile aggiungere codice al progetto MyDesktopWin32App per ospitare il controllo XAML WinRT personalizzato definito in precedenza nel progetto MyUWPApp.

  1. Nel progetto MyDesktopWin32App apri il file framework.h e imposta come commento la riga di codice seguente. Al termine, salva il file.

    #define WIN32_LEAN_AND_MEAN
    
  2. Apri il file MyDesktopWin32App.h e sostituisci il contenuto del file con il codice seguente in modo da fare riferimento ai file di intestazione C++/WinRT necessari. Al termine, salva il file.

    #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. Apri il file MyDesktopWin32App.cpp e aggiungi il codice seguente alla sezione Global Variables:.

    winrt::MyUWPApp::App hostApp{ nullptr };
    winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _desktopWindowXamlSource{ nullptr };
    winrt::MyUWPApp::MyUserControl _myUserControl{ nullptr };
    
  4. Nello stesso file aggiungi il codice seguente alla sezione Forward declarations of functions included in this code module:.

    void AdjustLayout(HWND);
    
  5. Nello stesso file aggiungi il codice seguente subito dopo il commento TODO: Place code here. nella funzione 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. Nello stesso file sostituisci la funzione InitInstance predefinita con il codice seguente.

    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. Nello stesso file aggiungi la nuova funzione seguente alla fine del file.

    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. Nello stesso file individua la funzione WndProc. Sostituisci il gestore WM_DESTROY predefinito nell'istruzione switch con il codice seguente.

    case WM_DESTROY:
        PostQuitMessage(0);
        if (_desktopWindowXamlSource != nullptr)
        {
            _desktopWindowXamlSource.Close();
            _desktopWindowXamlSource = nullptr;
        }
        break;
    case WM_SIZE:
        AdjustLayout(hWnd);
        break;
    
  9. Salva il file.

  10. Compila la soluzione e verifica che venga compilata correttamente.

Aggiungere un controllo dalla libreria WinUI 2 al controllo personalizzato

Tradizionalmente, i controlli XAML WinRT sono stati rilasciati come parte del sistema operativo Windows e resi disponibili agli sviluppatori tramite Windows SDK. La libreria WinUI è un approccio alternativo, in cui le versioni aggiornate dei controlli XAML WinRT di Windows SDK vengono distribuite in un pacchetto NuGet non associato a versioni di Windows SDK. Questa libreria include anche nuovi controlli che non fanno parte di Windows SDK e della piattaforma UWP predefinita.

Questa sezione illustra come aggiungere un controllo XAML WinRT della libreria WinUI 2 al controllo utente.

Nota

Le isole XAML supportano attualmente solo l'hosting dei controlli della libreria WinUI 2. Il supporto per l'hosting dei controlli della libreria WinUI 3 sarà disponibile in una versione successiva.

  1. Nel progetto MyUWPApp installa la versione preliminare o definitiva più recente del pacchetto NuGet Microsoft.UI.Xaml.

    • Se in precedenza in questa procedura dettagliata si è scelto di creare un pacchetto del progetto MyDesktopWin32App usando MSIX, è possibile installare la versione provvisoria o finale del pacchetto NugGet Microsoft.UI.Xaml. Le app desktop in pacchetto possono usare la versione provvisoria o finale del pacchetto.
    • Se si è scelto di non creare un pacchetto del progetto MyDesktopWin32App, è necessario installare la versione provvisoria del pacchetto NuGet Microsoft.UI.Xaml. Le app desktop non in pacchetto devono usare la versione provvisoria del pacchetto.
  2. Nel file pch.h di questo progetto aggiungi le istruzioni #include seguenti e salva le modifiche apportate. Queste istruzioni inseriscono un set obbligatorio di intestazioni di proiezione dalla libreria WinUI nel progetto. Questo passaggio è obbligatorio per qualsiasi progetto C++/WinRT che usa la libreria WinUI. Per altre informazioni, vedi questo articolo.

    #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. Nel file App.xaml dello stesso progetto aggiungi l'elemento figlio seguente all'elemento <xaml:XamlApplication> e salva le modifiche apportate.

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

    Dopo l'aggiunta di questo elemento, il contenuto di questo file dovrebbe avere un aspetto simile al seguente.

    <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. Nello stesso progetto apri il file MyUserControl.xaml e aggiungi la dichiarazione di spazio dei nomi seguente all'elemento <UserControl>.

    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    
  5. Nello stesso file aggiungi un elemento <winui:RatingControl /> come figlio dell'oggetto <StackPanel> e salva le modifiche apportate. Questo elemento aggiunge un'istanza della classe RatingControl dalla libreria WinUI. Dopo l'aggiunta di questo elemento, l'oggetto <StackPanel> dovrebbe avere un aspetto simile al seguente.

    <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. Compila la soluzione e verifica che venga compilata correttamente.

Testare l'app

Esegui la soluzione e verifica che l'app MyDesktopWin32App venga aperta con la finestra seguente.

MyDesktopWin32App app

Passaggi successivi

Molte applicazioni desktop che ospitano le isole XAML dovranno probabilmente gestire scenari aggiuntivi per offrire un'esperienza utente uniforme. Potrebbero ad esempio dover gestire l'input da tastiera nelle isole XAML, lo spostamento dello stato attivo tra le isole XAML e altri elementi dell'interfaccia utente e le modifiche di layout.

Per altre informazioni sulla gestione di questi scenari e per riferimenti a esempi di codice correlati, vedere Scenari avanzati per le isole XAML nelle app desktop C++.