แก้ไข

แชร์ผ่าน


Advanced scenarios for XAML Islands in C++ desktop (Win32) apps

Important

This topic uses or mentions types from the CommunityToolkit/Microsoft.Toolkit.Win32 GitHub repo. For important info about XAML Islands support, please see the XAML Islands Notice in that repo.

The host a standard UWP control and host a custom UWP control articles provide instructions and examples for hosting XAML Islands in a C++ desktop (Win32) app. However, the code examples in these articles do not handle many advanced scenarios that desktop applications may need to handle to provide a smooth user experience. This article provides guidance for some of these scenarios and pointers to related code samples.

Keyboard input

To properly handle keyboard input for each XAML Island, your application must pass all Windows messages to the UWP XAML framework so that certain messages can be processed correctly. To do this, in some place in your application that can access the message loop, cast the DesktopWindowXamlSource object for each XAML Island to an IDesktopWindowXamlSourceNative2 COM interface. Then, call the PreTranslateMessage method of this interface and pass in the current message.

Keyboard focus navigation

When the user navigates through the UI elements in your application using the keyboard (for example, by pressing Tab or direction/arrow key), you'll need to programmatically move focus into and out of the DesktopWindowXamlSource object. When the user's keyboard navigation reaches the DesktopWindowXamlSource, move focus into the first Windows.UI.Xaml.UIElement object in the navigation order for your UI, continue to move focus to the following Windows.UI.Xaml.UIElement objects as the user cycles through the elements, and then move focus back out of the DesktopWindowXamlSource and into the parent UI element.

The UWP XAML hosting API provides several types and members to help you accomplish these tasks.

  • When the keyboard navigation enters your DesktopWindowXamlSource, the GotFocus event is raised. Handle this event and programmatically move focus to the first hosted Windows.UI.Xaml.UIElement by using the NavigateFocus method.

  • When the user is on the last focusable element in your DesktopWindowXamlSource and presses the Tab key or an arrow key, the TakeFocusRequested event is raised. Handle this event and programmatically move focus to the next focusable element in the host application. For example, in a WPF application where the DesktopWindowXamlSource is hosted in a System.Windows.Interop.HwndHost, you can use the MoveFocus method to transfer focus to the next focusable element in the host application.

For examples that demonstrate how to do this in the context of a working sample application, see the following code files:

Handle layout changes

When the user changes the size of the parent UI element, you'll need to handle any necessary layout changes to make sure your UWP controls display as you expect. Here are some important scenarios to consider.

  • In a C++ desktop application, when your application handles the WM_SIZE message it can reposition the hosted XAML Island by using the SetWindowPos function. For an example, see the SampleApp.cpp code file.

  • When the parent UI element needs to get the size of the rectangular area needed to fit the Windows.UI.Xaml.UIElement that you are hosting on the DesktopWindowXamlSource, call the Measure method of the Windows.UI.Xaml.UIElement. For example:

  • When the size of the parent UI element changes, call the Arrange method of the root Windows.UI.Xaml.UIElement that you are hosting on the DesktopWindowXamlSource. For example:

    • In a WPF application you might do this from the ArrangeOverride method of the HwndHost object that hosts the DesktopWindowXamlSource. For an example, see the WindowsXamlHost.Layout.cs file in the Windows Community Toolkit.

    • In a Windows Forms application you might do this from the handler for the SizeChanged event of the Control that hosts the DesktopWindowXamlSource. For an example, see the WindowsXamlHost.Layout.cs file in the Windows Community Toolkit.

Handle DPI changes

The UWP XAML framework handles DPI changes for hosted UWP controls automatically (for example, when the user drags the window between monitors with different screen DPI). For the best experience, we recommend that your Windows Forms, WPF, or C++ desktop application is configured to be per-monitor DPI aware.

To configure your application to be per-monitor DPI aware, add a side-by-side assembly manifest to your project and set the <dpiAwareness> element to PerMonitorV2. For more information about this value, see the description for DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings>
            <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
        </windowsSettings>
    </application>
</assembly>