Menghosting kontrol WinRT XAML kustom di aplikasi desktop C++ (Win32)

Penting

Topik ini menggunakan atau menyebutkan jenis dari repositori GitHub CommunityToolkit/Microsoft.Toolkit.Win32 . Untuk informasi penting tentang dukungan Kepulauan XAML, silakan lihat Pemberitahuan Kepulauan XAML di repositori tersebut.

Artikel ini menunjukkan cara menggunakan API hosting WinRT XAML untuk menghosting kontrol WinRT XAML kustom di aplikasi desktop C++ baru. Jika Anda memiliki proyek aplikasi desktop C++ yang sudah ada, Anda dapat menyesuaikan langkah-langkah dan contoh kode ini untuk proyek Anda.

Untuk menghosting kontrol WinRT XAML kustom, Anda akan membuat proyek dan komponen berikut sebagai bagian dari panduan ini:

  • Proyek Aplikasi Desktop Windows. Proyek ini mengimplementasikan aplikasi desktop C++ asli. Anda akan menambahkan kode ke proyek ini yang menggunakan API hosting WinRT XAML untuk menghosting kontrol WinRT XAML kustom.

  • Proyek aplikasi UWP (C++/WinRT). Proyek ini mengimplementasikan kontrol WinRT XAML kustom. Ini juga mengimplementasikan penyedia metadata root untuk memuat metadata untuk jenis WinRT XAML kustom dalam proyek.

Persyaratan

  • Visual Studio 2019 versi 16.4.3 atau yang lebih baru.
  • Windows 10, SDK versi 1903 (versi 10.0.18362) atau yang lebih baru.
  • C++/WinRT Visual Studio Extension (VSIX) diinstal dengan Visual Studio. C++/WinRT adalah proyeksi bahasa C++17 modern yang sepenuhnya standar untuk API Windows Runtime (WinRT), yang diimplementasikan sebagai pustaka berbasis file header, dan dirancang untuk memberi Anda akses kelas satu ke Windows API modern. Untuk informasi selengkapnya, lihat C++/WinRT.

Membuat proyek aplikasi desktop

  1. Di Visual Studio, buat proyek Aplikasi Desktop Windows baru bernama MyDesktopWin32App. Templat proyek ini tersedia di bawah filter proyek C++, Windows, dan Desktop .

  2. Di Penjelajah Solusi, klik kanan simpul solusi, klik Solusi penargetan ulang, pilih rilis SDK 10.0.18362.0 atau yang lebih baru, lalu klik OK.

  3. Instal paket NuGet Microsoft.Windows.CppWinRT untuk mengaktifkan dukungan untuk C++/WinRT di proyek Anda:

    1. Klik kanan proyek MyDesktopWin32App di Penjelajah Solusi dan pilih Kelola Paket NuGet.
    2. Pilih tab Telusuri , cari paket Microsoft.Windows.CppWinRT , dan instal versi terbaru paket ini.
  4. Di jendela Kelola Paket NuGet, instal paket NuGet tambahan berikut:

  5. Tambahkan referensi ke metadata Windows Runtime:

    1. Di Penjelajah Solusi, klik kanan pada simpul Referensi proyek Anda dan pilih Tambahkan Referensi.
    2. Klik tombol Telusuri di bagian bawah halaman dan navigasikan ke folder UnionMetadata di jalur penginstalan SDK Anda. Secara default, SDK akan diinstal ke C:\Program Files (x86)\Windows Kits\10\UnionMetadata.
    3. Kemudian, pilih folder bernama sesuai versi Windows yang Anda targetkan (misalnya 10.0.18362.0) dan di dalam folder tersebut Windows.winmd pilih file.
    4. Klik OK untuk menutup dialog Tambahkan Referensi .
  6. Bangun solusi dan konfirmasikan bahwa solusi berhasil dibangun.

Membuat proyek aplikasi UWP

Selanjutnya, tambahkan proyek aplikasi UWP (C++/WinRT) ke solusi Anda dan buat beberapa perubahan konfigurasi pada proyek ini. Nanti dalam panduan ini, Anda akan menambahkan kode ke proyek ini untuk mengimplementasikan kontrol WinRT XAML kustom dan menentukan instans kelas Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication .

  1. Di Penjelajah Solusi, klik kanan simpul solusi dan pilih Tambahkan ->Proyek Baru.

  2. Tambahkan proyek Aplikasi Kosong (C++/WinRT) ke solusi Anda. Beri nama proyek MyUWPApp dan pastikan versi target dan versi minimum keduanya diatur ke Windows 10, versi 1903 atau yang lebih baru.

  3. Instal paket NuGet Microsoft.Toolkit.Win32.UI.XamlApplication di proyek MyUWPApp. Paket ini mendefinisikan kelas Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication , yang akan Anda gunakan nanti dalam panduan ini.

    1. Klik kanan proyek MyUWPApp dan pilih Kelola Paket NuGet.
    2. Pilih tab Telusuri , cari paket Microsoft.Toolkit.Win32.UI.XamlApplication , dan instal versi stabil terbaru paket ini.
  4. Klik kanan simpul MyUWPApp dan pilih Properti. Pada halaman Properti Umum ->C++/WinRT , atur properti Verbosity ke normal lalu klik Terapkan. Setelah selesai, halaman properti akan terlihat seperti ini.

    C++/WinRT project properties

  5. Pada halaman Properti Konfigurasi ->Umum jendela properti, atur Jenis Konfigurasi ke Pustaka Dinamis (.dll), lalu klik OK untuk menutup jendela properti.

    General project properties

  6. Tambahkan file yang dapat dieksekusi tempat penampung ke proyek MyUWPApp . File yang dapat dieksekusi tempat penampung ini diperlukan agar Visual Studio menghasilkan file proyek yang diperlukan dan membangun proyek dengan benar.

    1. Di Penjelajah Solusi, klik kanan simpul proyek MyUWPApp dan pilih Tambahkan ->Item Baru.

    2. Dalam dialog Tambahkan Item Baru, pilih Utilitas di halaman kiri, lalu pilih File Teks (.txt). Masukkan nama placeholder.exe dan klik Tambahkan. Add text file

    3. Di Penjelajah Solusi, pilih file placeholder.exe. Di jendela Properti , pastikan properti Konten diatur ke True.

    4. Di Penjelajah Solusi, klik kanan file Package.appxmanifest di proyek MyUWPApp, pilih Buka Dengan, dan pilih EDITOR XML (Teks), dan klik OK.

    5. <Temukan elemen Aplikasi> dan ubah atribut Executable ke nilai placeholder.exe. Setelah selesai, <elemen Aplikasi> akan terlihat mirip dengan ini.

      <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. Simpan dan tutup file Package.appxmanifest .

  7. Di Penjelajah Solusi, klik kanan simpul MyUWPApp dan pilih Bongkar Proyek.

  8. Klik kanan simpul MyUWPApp dan pilih Edit MyUWPApp.vcxproj.

  9. <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> Temukan elemen dan ganti dengan XML berikut. XML ini menambahkan beberapa properti baru segera sebelum elemen.

    <PropertyGroup Label="Globals">
        <WindowsAppContainer>true</WindowsAppContainer>
        <AppxGeneratePriEnabled>true</AppxGeneratePriEnabled>
        <ProjectPriIndexName>App</ProjectPriIndexName>
        <AppxPackage>true</AppxPackage>
    </PropertyGroup>
    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
    
  10. Simpan dan tutup file proyek.

  11. Di Penjelajah Solusi, klik kanan simpul MyUWPApp dan pilih Muat Ulang Proyek.

Mengonfigurasi solusi

Di bagian ini, Anda akan memperbarui solusi yang berisi kedua proyek untuk mengonfigurasi dependensi proyek dan membangun properti yang diperlukan agar proyek dibangun dengan benar.

  1. Di Penjelajah Solusi, klik kanan simpul solusi dan tambahkan file XML baru bernama Solution.props.

  2. Tambahkan XML berikut ke 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. Dari menu Tampilan, klik Pengelola Properti (tergantung konfigurasi Anda, ini mungkin ada di bawah Tampilkan ->Windows Lain).

  4. Di jendela Pengelola Properti, klik kanan MyDesktopWin32App dan pilih Tambahkan Lembar Properti yang Ada. Navigasi ke file Solution.props yang baru saja Anda tambahkan dan klik Buka.

  5. Ulangi langkah sebelumnya untuk menambahkan file Solution.props ke proyek MyUWPApp di jendela Pengelola Properti.

  6. Tutup jendela Pengelola Properti.

  7. Konfirmasikan bahwa perubahan lembar properti disimpan dengan benar. Di Penjelajah Solusi, klik kanan proyek MyDesktopWin32App dan pilih Properti. Klik Properti Konfigurasi ->Umum, dan konfirmasikan bahwa properti Direktori Output dan Direktori Perantara memiliki nilai yang Anda tambahkan ke file Solution.props . Anda juga dapat mengonfirmasi hal yang sama untuk proyek MyUWPApp . Project properties

  8. Di Penjelajah Solusi, klik kanan simpul solusi dan pilih Dependensi Proyek. Di menu drop-down Proyek, pastikan myDesktopWin32App dipilih, dan pilih MyUWPApp di daftar Depends On. Project dependencies

  9. Klik OK.

Menambahkan kode ke proyek aplikasi UWP

Anda sekarang siap untuk menambahkan kode ke proyek MyUWPApp untuk melakukan tugas-tugas ini:

Menentukan kontrol WinRT XAML kustom

  1. Di Penjelajah Solusi, klik kanan MyUWPApp dan pilih Tambahkan ->Item Baru. Pilih simpul Visual C++ di panel kiri, pilih Kontrol Pengguna Kosong (C++/WinRT), beri nama MyUserControl, dan klik Tambahkan.

  2. Di editor XAML, ganti konten file MyUserControl.xaml dengan XAML berikut lalu simpan 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>
    

Menentukan kelas XamlApplication

Selanjutnya, revisi kelas Aplikasi default di proyek MyUWPApp untuk berasal dari kelas Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication yang disediakan oleh Windows Community Toolkit. Kelas ini mendukung antarmuka IXamlMetadataProvider , yang memungkinkan aplikasi Anda menemukan dan memuat metadata untuk kontrol WinRT XAML kustom dalam rakitan di direktori aplikasi Anda saat ini pada waktu proses. Kelas ini juga menginisialisasi kerangka kerja WinRT XAML untuk utas saat ini. Nanti dalam panduan ini Anda akan memperbarui proyek desktop untuk membuat instans kelas ini.

Catatan

Setiap solusi yang menggunakan Kepulauan XAML hanya dapat berisi satu proyek yang menentukan XamlApplication objek. Semua kontrol WinRT XAML kustom di aplikasi Anda memiliki objek yang sama XamlApplication .

  1. Di Penjelajah Solusi, klik kanan file MainPage.xaml di proyek MyUWPApp. Klik Hapus lalu Hapus untuk menghapus file ini secara permanen dari proyek.

  2. Dalam proyek MyUWPApp, perluas file App.xaml.

  3. Ganti konten file App.xaml, App.cpp, App.h, dan App.idl dengan kode berikut.

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

      Catatan

      Pernyataan #include "App.g.cpp" ini diperlukan ketika properti Yang Dioptimalkan pada halaman Properti Umum ->C++/WinRT dari properti proyek diatur ke Ya. Ini adalah default untuk proyek C++/WinRT baru. Untuk detail selengkapnya tentang efek properti Yang Dioptimalkan, lihat bagian ini.

  4. Tambahkan file header baru ke proyek MyUWPApp bernama app.base.h.

  5. Tambahkan kode berikut ke file app.base.h , simpan file, dan tutup.

    #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. Bangun solusi dan konfirmasikan bahwa solusi berhasil dibangun.

Mengonfigurasi proyek desktop untuk menggunakan jenis kontrol kustom

Sebelum aplikasi MyDesktopWin32App dapat menghosting kontrol WinRT XAML kustom di Pulau XAML, aplikasi harus dikonfigurasi untuk menggunakan jenis kontrol kustom dari proyek MyUWPApp. Ada dua cara untuk melakukan ini, dan Anda dapat memilih salah satu opsi saat Anda menyelesaikan panduan ini.

Opsi 1: Mengemas aplikasi menggunakan MSIX

Anda dapat mengemas aplikasi dalam paket MSIX untuk penyebaran. MSIX adalah teknologi pengemasan aplikasi modern untuk Windows, dan didasarkan pada kombinasi teknologi penginstalan MSI, .appx, App-V, dan ClickOnce.

  1. Tambahkan Proyek Pengemasan Aplikasi Windows baru ke solusi Anda. Saat Anda membuat proyek, beri nama MyDesktopWin32Project dan pilih Windows 10, versi 1903 (10.0; Build 18362) untuk versi Target dan Versi minimum.

  2. Dalam proyek pengemasan, klik kanan simpul Aplikasi dan pilih Tambahkan referensi. Dalam daftar proyek, pilih kotak centang di samping proyek MyDesktopWin32App dan klik OK. Reference project

  3. Untuk informasi tentang mendistribusikan/menyebarkan paket, lihat Mengelola penyebaran MSIX Anda.

Catatan

Jika Anda memilih untuk tidak mengemas aplikasi Anda dalam paket MSIX untuk penyebaran, komputer yang menjalankan aplikasi Anda harus menginstal Visual C++ Runtime .

Opsi 2: Membuat manifes aplikasi

Anda dapat menambahkan manifes aplikasi ke aplikasi Anda.

  1. Klik kanan proyek MyDesktopWin32App dan pilih Tambahkan ->Item Baru.

  2. Dalam dialog Tambahkan Item Baru, klik Web di panel kiri dan pilih File XML (.xml).

  3. Beri nama file baru app.manifest dan klik Tambahkan.

  4. Ganti konten file baru dengan XML berikut. XML ini mendaftarkan jenis kontrol kustom dalam proyek 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>
    

Mengonfigurasi properti proyek desktop tambahan

Selanjutnya, perbarui proyek MyDesktopWin32App untuk menentukan makro untuk direktori sertakan tambahan dan konfigurasikan properti tambahan.

  1. Di Penjelajah Solusi, klik kanan proyek MyDesktopWin32App dan pilih Bongkar Proyek.

  2. Klik kanan MyDesktopWin32App (Tidak Dimuat) dan pilih Edit MyDesktopWin32App.vcxproj.

  3. Tambahkan XML berikut tepat sebelum tag penutup </Project> di akhir file. Kemudian, simpan dan tutup 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. Di Penjelajah Solusi, klik kanan MyDesktopWin32App (dibongkar) dan pilih Muat Ulang Proyek.

  5. Klik kanan proyek MyDesktopWin32App, pilih Properti, dan perluas Alat Manifes ->Input dan Output di panel kiri. Atur properti Kesadaran DPI ke Per Monitor Sadar DPI Tinggi. Jika Anda tidak mengatur properti ini, Anda mungkin mengalami kesalahan konfigurasi manifes dalam skenario DPI tinggi tertentu.

    Screenshot of the C/C++ project settings.

  6. Klik OK untuk menutup dialog Halaman Properti.

Menghosting kontrol WinRT XAML kustom di proyek desktop

Terakhir, Anda siap untuk menambahkan kode ke proyek MyDesktopWin32App untuk menghosting kontrol WinRT XAML kustom yang Anda tentukan sebelumnya di proyek MyUWPApp .

  1. Dalam proyek MyDesktopWin32App, buka file framework.h dan komentari baris kode berikut. Simpan file saat Anda selesai.

    #define WIN32_LEAN_AND_MEAN
    
  2. Buka file MyDesktopWin32App.h dan ganti konten file ini dengan kode berikut untuk mereferensikan file header C++/WinRT yang diperlukan. Simpan file saat Anda selesai.

    #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. Buka file MyDesktopWin32App.cpp dan tambahkan kode berikut ke bagian .Global Variables:

    winrt::MyUWPApp::App hostApp{ nullptr };
    winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _desktopWindowXamlSource{ nullptr };
    winrt::MyUWPApp::MyUserControl _myUserControl{ nullptr };
    
  4. Dalam file yang sama, tambahkan kode berikut ke bagian Forward declarations of functions included in this code module: .

    void AdjustLayout(HWND);
    
  5. Dalam file yang sama, tambahkan kode berikut segera setelah TODO: Place code here. komentar dalam wWinMain fungsi .

    // TODO: Place code here.
    winrt::init_apartment(winrt::apartment_type::single_threaded);
    hostApp = winrt::MyUWPApp::App{};
    _desktopWindowXamlSource = winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource{};
    
  6. Dalam file yang sama, ganti fungsi default InitInstance dengan kode berikut.

    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. Dalam file yang sama, tambahkan fungsi baru berikut ke akhir 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. Dalam file yang sama, temukan WndProc fungsi . Ganti handler default WM_DESTROY dalam pernyataan pengalihan dengan kode berikut.

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

  10. Bangun solusi dan konfirmasikan bahwa solusi berhasil dibangun.

Menambahkan kontrol dari pustaka WinUI 2 ke kontrol kustom

Secara tradisional, kontrol WinRT XAML telah dirilis sebagai bagian dari OS Windows dan tersedia untuk pengembang melalui Windows SDK. Pustaka WinUI adalah pendekatan alternatif, di mana versi kontrol WinRT XAML yang diperbarui dari Windows SDK didistribusikan dalam paket NuGet yang tidak terkait dengan rilis Windows SDK. Pustaka ini juga mencakup kontrol baru yang bukan bagian dari Windows SDK dan platform UWP default.

Bagian ini menunjukkan cara menambahkan kontrol WinRT XAML dari pustaka WinUI 2 ke kontrol pengguna Anda.

Catatan

Saat ini, Kepulauan XAML hanya mendukung kontrol hosting dari pustaka WinUI 2. Dukungan untuk kontrol hosting dari pustaka WinUI 3 akan hadir dalam rilis selanjutnya.

  1. Dalam proyek MyUWPApp, instal versi prarilis atau rilis terbaru dari paket NuGet Microsoft.UI.Xaml.

  2. Dalam file pch.h dalam proyek ini, tambahkan pernyataan berikut #include dan simpan perubahan Anda. Pernyataan ini membawa sekumpulan header proyeksi yang diperlukan dari pustaka WinUI ke dalam proyek Anda. Langkah ini diperlukan untuk setiap proyek C++/WinRT yang menggunakan pustaka WinUI. Untuk informasi selengkapnya, lihat artikel ini.

    #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. Dalam file App.xaml dalam proyek yang sama, tambahkan elemen turunan berikut ke <xaml:XamlApplication> elemen dan simpan perubahan Anda.

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

    Setelah menambahkan elemen ini, konten file ini sekarang akan terlihat mirip dengan ini.

    <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. Dalam proyek yang sama, buka file MyUserControl.xaml dan tambahkan deklarasi namespace berikut ke <UserControl> elemen .

    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    
  5. Dalam file yang sama, tambahkan <winui:RatingControl /> elemen sebagai anak dari <StackPanel> dan simpan perubahan Anda. Elemen ini menambahkan instans kelas RatingControl dari pustaka WinUI. Setelah menambahkan elemen ini, <StackPanel> sekarang akan terlihat mirip dengan ini.

    <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. Bangun solusi dan konfirmasikan bahwa solusi berhasil dibangun.

Menguji aplikasi

Jalankan solusi dan konfirmasikan bahwa MyDesktopWin32App terbuka dengan jendela berikut.

MyDesktopWin32App app

Langkah berikutnya

Banyak aplikasi desktop yang menghosting Kepulauan XAML harus menangani skenario tambahan untuk memberikan pengalaman pengguna yang lancar. Misalnya, aplikasi desktop mungkin perlu menangani input keyboard di Kepulauan XAML, navigasi fokus antara Kepulauan XAML dan elemen UI lainnya, dan perubahan tata letak.

Untuk informasi selengkapnya tentang menangani skenario dan penunjuk ini ke sampel kode terkait, lihat Skenario tingkat lanjut untuk Kepulauan XAML di aplikasi desktop C++.