Udostępnij przez


Tworzenie niestandardowej kontrolki XAML WinRT w klasycznej aplikacji desktopowej C++ (Win32)

Ważne

W tym temacie wykorzystywane lub wspomniane są typy z repozytorium GitHub CommunityToolkit/Microsoft.Toolkit.Win32. Aby uzyskać ważne informacje o obsłudze wysp XAML, zobacz XAML Islands Notice w tym repozytorium.

W tym artykule pokazano, jak używać interfejsu API hostingu WinRT XAML do hostowania niestandardowej kontrolki WinRT XAML w nowej aplikacji komputerowej C++. Jeśli masz istniejący projekt aplikacji klasycznej w języku C++, możesz dostosować te kroki i przykłady kodu dla projektu.

Aby hostować niestandardową kontrolkę XAML winRT, utworzysz następujące projekty i składniki w ramach tego przewodnika:

  • projekt aplikacji desktopowej Windows. Ten projekt implementuje natywną aplikację klasyczną języka C++. Dodasz kod do tego projektu, który używa interfejsu API hostowania XAML WinRT, aby hostować niestandardową kontrolkę XAML WinRT.

  • projekt aplikacji UWP (C++/WinRT). Ten projekt implementuje niestandardową kontrolkę XAML winRT. Implementuje również podstawowego dostawcę metadanych do wczytywania metadanych dla niestandardowych typów XAML WinRT w projekcie.

Wymagania

  • Program Visual Studio 2019 w wersji 16.4.3 lub nowszej.
  • Windows 10, wersja 1903 SDK (wersja 10.0.18362) lub nowsza.
  • C++/WinRT Visual Studio Extension (VSIX) zainstalowane w programie Visual Studio. C++/WinRT to całkowicie standardowa nowoczesna projekcja języka C++17 dla interfejsów API środowiska Uruchomieniowego systemu Windows (WinRT), zaimplementowana jako biblioteka oparta na plikach nagłówków i zaprojektowana w celu zapewnienia najwyższej klasy dostępu do nowoczesnego interfejsu API systemu Windows. Aby uzyskać więcej informacji, zobacz C++/WinRT.

Utwórz projekt aplikacji desktopowej

  1. W programie Visual Studio utwórz nowy projekt aplikacji pulpitowej systemu Windows o nazwie MyDesktopWin32App. Ten szablon projektu jest dostępny w filtrach projektów C++, Windows i Desktop .

  2. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł rozwiązania, kliknij Retarget solution, wybierz 10.0.18362.0 lub nowszą wersję zestawu SDK, a następnie kliknij przycisk OK.

  3. Zainstaluj pakiet Microsoft.Windows.CppWinRT NuGet, aby umożliwić obsługę C++/WinRT w projekcie:

    1. Kliknij prawym przyciskiem myszy projekt MyDesktopWin32App w Eksploratorze rozwiązań i wybierz polecenie Zarządzaj pakietami NuGet.
    2. Wybierz kartę Przeglądaj, wyszukaj pakiet Microsoft.Windows.CppWinRT i zainstaluj najnowszą wersję tego pakietu.
  4. W oknie Zarządzanie pakietami NuGet zainstaluj następujące dodatkowe pakiety NuGet:

  5. Dodaj odwołanie do metadanych środowiska uruchomieniowego systemu Windows:

    1. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł 'Odwołania' projektu i wybierz pozycję Dodaj odwołanie.
    2. Kliknij przycisk Przeglądaj w dolnej części strony i przejdź do folderu UnionMetadata w ścieżce instalacji zestawu SDK. Domyślnie SDK będzie instalowane do C:\Program Files (x86)\Windows Kits\10\UnionMetadata.
    3. Następnie wybierz folder o nazwie po docelowej wersji systemu Windows (np. 10.0.18362.0) i wewnątrz tego folderu wybierz Windows.winmd plik.
    4. Kliknij przycisk OK, aby zamknąć okno dialogowe Dodaj odwołanie.
  6. Skompiluj rozwiązanie i potwierdź, że kompiluje się pomyślnie.

Utwórz projekt aplikacji UWP

Następnie dodaj UWP (C++/WinRT) projekt aplikacji do rozwiązania i wprowadź pewne zmiany konfiguracji w tym projekcie. Później w tym przewodniku wstawisz kod w tym projekcie, aby zaimplementować niestandardową kontrolkę XAML WinRT i zdefiniować wystąpienie klasy Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication.

  1. W eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł rozwiązania i wybierz pozycję Dodaj —>Nowy Projekt.

  2. Dodaj do rozwiązania projekt pustej aplikacji (C++/WinRT). Nadaj projektowi nazwę MyUWPApp i upewnij się, że wersja docelowa i minimalna są ustawione na Windows 10 w wersji 1903 lub nowszej.

  3. Zainstaluj pakiet NuGet Microsoft.Toolkit.Win32.UI.XamlApplication w projekcie MyUWPApp . Ten pakiet definiuje klasę Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication , która będzie używana w dalszej części tego przewodnika.

    1. Kliknij prawym przyciskiem myszy projekt MyUWPApp i wybierz polecenie Zarządzaj pakietami NuGet.
    2. Wybierz kartę Przeglądaj, wyszukaj pakiet Microsoft.Toolkit.Win32.UI.XamlApplication i zainstaluj najnowszą stabilną wersję tego pakietu.
  4. Kliknij prawym przyciskiem myszy węzeł MyUWPApp i wybierz Właściwości . Na stronie Common Properties ->C++/WinRT ustaw właściwość Verbosity na normalną, a następnie kliknij Zastosuj. Po zakończeniu strona właściwości powinna wyglądać następująco.

    Zrzut ekranu przedstawiający stronę Właściwości projektu z wybraną pozycją Właściwości wspólne — C++/WinRT, wyróżnioną właściwością Verbosity i ustawioną wartością „normal”.

  5. Na stronie właściwości konfiguracji —>ogólne okna właściwości ustaw typ konfiguracjibiblioteki dynamicznej (.dll), a następnie kliknij przycisk OK, aby zamknąć okno właściwości.

    Zrzut ekranu przedstawiający stronę Właściwości projektu z wybraną pozycją Właściwości konfiguracji — ogólne, wyróżnioną właściwością Typ konfiguracji i ustawioną wartością

  6. Dodaj plik wykonywalny symbolu zastępczego do projektu MyUWPApp. Ten zastępczy plik wykonywalny jest wymagany, aby program Visual Studio wygenerował wymagane pliki projektu i prawidłowo skompilował projekt.

    1. W Eksploratorze Rozwiązań kliknij prawym przyciskiem myszy węzeł projektu MyUWPApp i wybierz pozycję Dodaj —>Nowy Element.

    2. W oknie dialogowym Dodawanie nowego elementu wybierz pozycję Narzędzie po lewej stronie, a następnie wybierz pozycję Plik tekstowy (.txt). Wprowadź nazwę placeholder.exe i kliknij przycisk Dodaj. Zrzut ekranu przedstawiający okno dialogowe Dodaj nowy element z wybraną opcją Visual C++ — Narzędzie, zaznaczoną opcją Plik tekstowy i ciągiem

    3. W Eksploratorze rozwiązań wybierz plik placeholder.exe . W oknie Właściwości upewnij się, że właściwość Content jest ustawiona na wartość True.

    4. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy plik Package.appxmanifest w projekcie MyUWPApp, wybierz pozycję Otwórz za pomocąi wybierz Edytor XML (tekstowy), a następnie kliknij przycisk OK.

    5. Znajdź element <Application> i zmień atrybut Wykonywalny na wartość placeholder.exe. Gdy skończysz, element <Application> powinien wyglądać podobnie do tego.

      <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. Zapisz i zamknij plik Package.appxmanifest .

  7. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy na węźle MyUWPApp i wybierz pozycję Wyładuj projekt.

  8. Kliknij prawym przyciskiem myszy węzeł MyUWPApp i wybierz pozycję Edytuj MyUWPApp.vcxproj.

  9. <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> Znajdź element i zastąp go następującym kodem XML. Ten kod XML dodaje kilka nowych właściwości bezpośrednio przed elementem.

    <PropertyGroup Label="Globals">
        <WindowsAppContainer>true</WindowsAppContainer>
        <AppxGeneratePriEnabled>true</AppxGeneratePriEnabled>
        <ProjectPriIndexName>App</ProjectPriIndexName>
        <AppxPackage>true</AppxPackage>
    </PropertyGroup>
    <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
    
  10. Zapisz i zamknij plik projektu.

  11. W eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł MyUWPApp i wybierz pozycję Załaduj ponownie projekt.

Konfigurowanie rozwiązania

W tej sekcji zaktualizujesz rozwiązanie zawierające oba projekty, aby skonfigurować zależności projektu i właściwości kompilacji wymagane do poprawnego kompilowania projektów.

  1. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy węzeł rozwiązania i dodaj nowy plik XML o nazwie Solution.props.

  2. Dodaj następujący kod XML do pliku 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. W menu View kliknij pozycję Property Manager (w zależności od konfiguracji może to być w obszarze View ->Other Windows).

  4. W oknie menedżera właściwości kliknij prawym przyciskiem myszy MyDesktopWin32App i wybierz pozycję Dodaj istniejący arkusz właściwości. Przejdź do pliku Solution.props, który właśnie dodałeś, i kliknij Otwórz.

  5. Powtórz poprzedni krok, aby dodać plik Solution.props do projektu MyUWPApp w oknie Menedżera właściwości .

  6. Zamknij okno Menedżer właściwości .

  7. Upewnij się, że zmiany arkusza właściwości zostały poprawnie zapisane. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt MyDesktopWin32App i wybierz Właściwości. Kliknij Właściwości Konfiguracji –>Ogólne, i upewnij się, że właściwości Katalog Wyjściowy i Katalog Pośredni mają wartości dodane do pliku Solution.props. Możesz również potwierdzić to samo dla projektu MyUWPApp . Zrzut ekranu przedstawiający stronę Właściwości projektu z wybraną właściwością konfiguracji — ogólne i wyświetlonymi właściwościami ogólnymi.

  8. W Eksploratorze rozwiązań , kliknij prawym przyciskiem myszy na węzeł rozwiązania i wybierz Zależności projektu. Na rozwijanej liście Projects upewnij się, że wybrano MyDesktopWin32App, a następnie wybierz MyUWPApp na liście Zależy od. Zrzut ekranu przedstawiający okno dialogowe Zależności projektu z bieżącym projektem wybranym z rozwijanej listy Projekty i zaznaczoną zależnością MyUWPApp w panelu

  9. Kliknij przycisk OK.

Dodawanie kodu do projektu aplikacji platformy UWP

Teraz możesz dodać kod do projektu MyUWPApp , aby wykonać następujące zadania:

  • Zaimplementuj niestandardową kontrolkę XAML winRT. W dalszej części tego przewodnika dodasz kod hostujący tę kontrolkę w projekcie MyDesktopWin32App .
  • Zdefiniuj typ pochodzący z klasy Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication w zestawie narzędzi Społeczności systemu Windows.

Definiowanie niestandardowej kontrolki XAML winRT

  1. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy MyUWPApp i wybierz Dodaj —>Nowy Element. Wybierz węzeł Visual C++ w lewym panelu, wybierz Pustą kontrolę użytkownika (C++/WinRT), nadaj jej nazwę MyUserControl, a następnie kliknij Dodaj.

  2. W edytorze XAML zastąp zawartość pliku MyUserControl.xaml następującym kodem XAML, a następnie zapisz plik.

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

Definiowanie klasy XamlApplication

Następnie zrewiduj domyślną klasę App w projekcie MyUWPApp, aby była pochodną klasy Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication dostarczonej przez Windows Community Toolkit. Ta klasa obsługuje interfejs IXamlMetadataProvider, który umożliwia aplikacji odnajdywanie i ładowanie metadanych niestandardowych kontrolek XAML WinRT w zestawach znajdujących się w bieżącym katalogu aplikacji podczas działania. Ta klasa inicjuje również strukturę XAML winRT dla bieżącego wątku. W dalszej części tego przewodnika zaktualizujesz projekt aplikacji komputerowej, aby utworzyć wystąpienie tej klasy.

Uwaga / Notatka

Każde rozwiązanie korzystające z wysp XAML może zawierać tylko jeden projekt definiujący XamlApplication obiekt. Wszystkie niestandardowe kontrolki XAML winRT w aplikacji współdzielą ten sam XamlApplication obiekt.

  1. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy plik MainPage.xaml w projekcie MyUWPApp . Kliknij przycisk Usuń , a następnie usuń , aby trwale usunąć ten plik z projektu.

  2. W projekcie MyUWPApp rozwiń plik App.xaml.

  3. Zastąp zawartość plików App.xaml, App.cpp, App.hi App.idl następującym kodem.

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

      Uwaga / Notatka

      Instrukcja #include "App.g.cpp" jest niezbędna, gdy właściwość Optimized w Common Properties —>C++/WinRT na stronie właściwości projektu jest ustawiona na Tak. Jest to ustawienie domyślne dla nowych projektów C++/WinRT. Aby uzyskać więcej informacji na temat efektów właściwości Optimized, zobacz tej sekcji.

  4. Dodaj nowy plik nagłówka do projektu MyUWPApp o nazwie app.base.h.

  5. Dodaj następujący kod do pliku app.base.h , zapisz plik i zamknij go.

    #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. Skompiluj rozwiązanie i potwierdź, że kompiluje się pomyślnie.

Skonfiguruj projekt pulpitu, aby wykorzystać niestandardowe typy kontrolek

Aby aplikacja MyDesktopWin32App mogła hostować niestandardową kontrolkę XAML WinRT na wyspie XAML, należy skonfigurować ją do korzystania z niestandardowych typów kontrolek z projektu MyUWPApp. Istnieją dwa sposoby, aby to zrobić, i można wybrać jedną z opcji podczas wykonywania tego przewodnika.

Opcja 1. Spakowanie aplikacji przy użyciu pliku MSIX

Aplikację można spakować do pakietu MSIX na potrzeby wdrożenia. MSIX to nowoczesna technologia tworzenia pakietów aplikacji dla systemu Windows, która jest oparta na połączeniu technologii instalacyjnych MSI, .appx, App-V i ClickOnce.

  1. Dodaj nowy projekt pakietowania aplikacji Windows do swojego rozwiązania. Podczas tworzenia projektu nadaj mu nazwę MyDesktopWin32Project i wybierz Windows 10, wersja 1903 (10.0; Kompilacja 18362) dla Wersji docelowej i Minimalna wersja.

  2. W projekcie pakowania kliknij prawym przyciskiem myszy na węzeł Aplikacje i wybierz opcję Dodaj referencję. Na liście projektów zaznacz pole wyboru obok projektu MyDesktopWin32App i kliknij przycisk OK. Zrzut ekranu przedstawiający okno dialogowe Menedżera referencji dla projektu pakowania z bieżącym projektem ustawionym jako referencja.

  3. Aby uzyskać informacje o dystrybucji/wdrażaniu pakietu, zobacz Zarządzanie wdrożeniem MSIX.

Uwaga / Notatka

Jeśli zdecydujesz się nie spakować aplikacji w pakiet MSIX do wdrożenia, komputery, na których działa twoja aplikacja, muszą mieć zainstalowane środowisko uruchomieniowe Visual C++.

Opcja 2. Tworzenie manifestu aplikacji

Można dodać manifest aplikacji do swojej aplikacji.

  1. Kliknij prawym przyciskiem myszy projekt MyDesktopWin32App i wybierz Dodaj ->Nowy Element.

  2. W oknie dialogowym Dodawanie nowego elementu kliknij Web w lewym okienku i wybierz opcję Plik XML (.xml).

  3. Nazwij nowy plik app.manifest i kliknij przycisk Dodaj.

  4. Zastąp zawartość nowego pliku następującym kodem XML. Ten kod XML rejestruje niestandardowe typy kontrolek w projekcie 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>
    

Konfigurowanie dodatkowych właściwości projektu pulpitu

Następnie zaktualizuj projekt MyDesktopWin32App , aby zdefiniować makro dla dodatkowych katalogów dołączania i skonfigurować dodatkowe właściwości.

  1. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy projekt MyDesktopWin32App i wybierz Wyładuj projekt.

  2. Kliknij prawym przyciskiem myszy MyDesktopWin32App (niezaładowany) i wybierz pozycję Edytuj MyDesktopWin32App.vcxproj.

  3. Dodaj następujący kod XML tuż przed tagiem zamykającym </Project> na końcu pliku. Następnie zapisz i zamknij plik.

      <!-- 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. W Eksploratorze rozwiązań kliknij prawym przyciskiem myszy MyDesktopWin32App (niezaładowany) i wybierz Załaduj ponownie projekt.

  5. Kliknij prawym przyciskiem myszy projekt MyDesktopWin32App, wybierz Właściwości i rozwiń, Narzędzie manifestu —>Wejście i wyjście w okienku po lewej stronie. Ustaw właściwość rozpoznawania DPI na na monitoro wysokiej rozdzielczości DPI. Jeśli ta właściwość nie zostanie ustawiona, może wystąpić błąd konfiguracji manifestu w niektórych scenariuszach o wysokiej rozdzielczości DPI.

    Zrzut ekranu przedstawiający stronę Właściwości bieżącego projektu z właściwościami konfiguracji — narzędzie manifestu — wybrane dane wejściowe i wyjściowe oraz rozpoznawanie dpi ustawione na wartość

  6. Kliknij przycisk OK, aby zamknąć okno dialogowe karty właściwości.

Hostowanie niestandardowej kontrolki WinRT XAML w projekcie dla komputerów stacjonarnych

Na koniec możesz dodać kod do projektu MyDesktopWin32App, aby hostować niestandardową kontrolkę XAML WinRT zdefiniowaną wcześniej w projekcie MyUWPApp.

  1. W projekcie MyDesktopWin32App otwórz plik framework.h i oznacz jako komentarz następujący wiersz kodu. Zapisz plik po zakończeniu.

    #define WIN32_LEAN_AND_MEAN
    
  2. Otwórz plik MyDesktopWin32App.h i zastąp zawartość tego pliku następującym kodem, aby odwołać się do niezbędnych plików nagłówków C++/WinRT. Zapisz plik po zakończeniu.

    #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. Otwórz plik MyDesktopWin32App.cpp i dodaj następujący kod do Global Variables: sekcji.

    winrt::MyUWPApp::App hostApp{ nullptr };
    winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _desktopWindowXamlSource{ nullptr };
    winrt::MyUWPApp::MyUserControl _myUserControl{ nullptr };
    
  4. W tym samym pliku dodaj następujący kod do Forward declarations of functions included in this code module: sekcji .

    void AdjustLayout(HWND);
    
  5. W tym samym pliku dodaj następujący kod bezpośrednio po komentarzu TODO: Place code here. w funkcji 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. W tym samym pliku zastąp funkcję domyślną InitInstance następującym kodem.

    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. W tym samym pliku dodaj następującą nową funkcję na końcu pliku.

    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. W tym samym pliku znajdź funkcję WndProc. Zastąp domyślną procedurę obsługi WM_DESTROY w instrukcji switch następującym kodem.

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

  10. Skompiluj rozwiązanie i potwierdź, że kompiluje się pomyślnie.

Dodawanie kontrolki z biblioteki WinUI 2 do kontrolki niestandardowej

Tradycyjnie kontrolki XAML środowiska WinRT zostały wydane w ramach systemu operacyjnego Windows i udostępnione deweloperom za pośrednictwem zestawu Windows SDK. Biblioteka WinUI jest alternatywną metodą, w której zaktualizowane wersje kontrolek XAML WinRT z zestawu Windows SDK są dystrybuowane w pakiecie NuGet, który nie jest powiązany z wydaniami zestawu Windows SDK. Ta biblioteka zawiera również nowe kontrolki, które nie są częścią zestawu Windows SDK i domyślnej platformy uwP.

W tej sekcji pokazano, jak dodać kontrolkę XAML WinRT z biblioteki WinUI 2 do kontrolki użytkownika.

Uwaga / Notatka

Obecnie XAML Islands obsługują tylko kontrolki z biblioteki WinUI 2. Obsługa kontrolek hostingu z biblioteki WinUI 3 jest dostępna w nowszej wersji.

  1. W projekcie MyUWPApp zainstaluj najnowszą wersję wstępną lub wersję pakietu NuGet Microsoft.UI.Xaml .

    • Jeśli zdecydujesz się pakiet projektu MyDesktopWin32App przy użyciu MSIX wcześniej w tym przewodniku, możesz zainstalować wersję wstępną lub wersję pakietu Microsoft.UI.Xaml NugGet. Spakowane aplikacje desktopowe mogą używać wersji przedpremierowej lub wersji wydanej tego pakietu.
    • Jeśli nie zdecydowałeś się na pakietowanie projektu MyDesktopWin32App, musisz zainstalować wersję prerelease pakietu NuGet Microsoft.UI.Xaml. Niezapakowane aplikacje desktopowe muszą używać wersji wstępnej tego pakietu.
  2. W pliku pch.h w tym projekcie dodaj następujące #include instrukcje i zapisz zmiany. Te instrukcje umożliwiają wprowadzenie wymaganego zestawu nagłówków projekcji z biblioteki WinUI do projektu. Ten krok jest wymagany dla dowolnego projektu C++/WinRT korzystającego z biblioteki WinUI. Aby uzyskać więcej informacji, zobacz ten artykuł.

    #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. W pliku App.xaml w tym samym projekcie dodaj następujący element podrzędny do <xaml:XamlApplication> elementu i zapisz zmiany.

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

    Po dodaniu tego elementu zawartość tego pliku powinna teraz wyglądać podobnie do tego.

    <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. W tym samym projekcie otwórz plik MyUserControl.xaml i dodaj następującą deklarację przestrzeni nazw do <UserControl> elementu .

    xmlns:winui="using:Microsoft.UI.Xaml.Controls"
    
  5. W tym samym pliku dodaj <winui:RatingControl /> element jako element podrzędny <StackPanel> i zapisz zmiany. Ten element dodaje instancję klasy RatingControl z biblioteki WinUI. Po dodaniu tego elementu <StackPanel> powinien wyglądać teraz podobnie.

    <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. Skompiluj rozwiązanie i potwierdź, że kompiluje się pomyślnie.

Testowanie aplikacji

Uruchom rozwiązanie i upewnij się, że aplikacja MyDesktopWin32App zostanie otwarta przy użyciu następującego okna.

Zrzut ekranu przedstawiający aplikację MyDesktopWin32App pokazaną w tym temacie.

Dalsze kroki

Wiele aplikacji komputerowych hostujących wyspy XAML będzie musiało obsługiwać dodatkowe scenariusze, aby zapewnić bezproblemowe doświadczenie użytkownika. Na przykład aplikacje desktopowe mogą wymagać obsługi danych wejściowych z klawiatury na wyspach XAML, nawigacji między wyspami XAML a innymi elementami interfejsu użytkownika oraz zmian układu.

Aby uzyskać więcej informacji na temat obsługi tych scenariuszy oraz referencje do powiązanych przykładów kodu, zobacz Zaawansowane scenariusze dla XAML Islands w aplikacjach desktopowych w C++.