C++ デスクトップ (Win32) アプリでの XAML Islands の高度なシナリオ

重要

このトピックでは、CommunityToolkit/Microsoft.Toolkit.Win32 GitHub リポジトリの型について使用または言及します。 XAML Islands のサポートに関する重要な情報については、そのリポジトリの XAML Islands に関する通知を参照してください。

標準 UWP コントロールのホストおよびカスタム UWP コントロールのホストに関する記事では、C++ デスクトップ (Win32) アプリで XAML Islands をホストするための手順と例が提供されています。 ただし、これらの記事のコード例では、円滑なユーザー エクスペリエンスを提供するためにデスクトップ アプリケーションで処理する必要がある多くの高度なシナリオについては扱われていません。 この記事では、これらのシナリオのいくつかに関するガイダンスを提供し、関連するコード サンプルを示します。

キーボード入力

各 XAML Island に対するキーボード入力を正しく処理するには、特定のメッセージが正しく処理されるように、アプリケーションですべての Windows メッセージを UWP XAML フレームワークに渡す必要があります。 これを行うには、メッセージ ループにアクセスできるアプリケーション内の場所で、各 XAML Island の DesktopWindowXamlSource オブジェクトを、IDesktopWindowXamlSourceNative2 COM インターフェイスにキャストします。 次に、このインターフェイスの PreTranslateMessage メソッドを呼び出して、現在のメッセージを渡します。

  • C++ デスクトップ (Win32): アプリのメイン メッセージ ループ内で PreTranslateMessage を直接呼び出すことができます。 例については、XamlBridge.cpp ファイルをご覧ください。

  • WPF: アプリでは、ComponentDispatcher.ThreadFilterMessage イベントのイベント ハンドラーから PreTranslateMessage を呼び出すことができます。 例については、Windows Community Toolkit の WindowsXamlHostBase.Focus.cs ファイルをご覧ください。

  • Windows フォーム: アプリでは、Control.PreprocessMessage メソッドのオーバーライドから、PreTranslateMessage を呼び出すことができます。 例については、Windows Community Toolkit の WindowsXamlHostBase.KeyboardFocus.cs ファイルをご覧ください。

キーボード フォーカスのナビゲーション

ユーザーがキーボードを使用してアプリケーションの UI 要素間を移動したとき (たとえば、Tab キーや方向キーが押された場合)、DesktopWindowXamlSource オブジェクトに、またはオブジェクトから、プログラムでフォーカスを移動する必要があります。 ユーザーのキーボード ナビゲーションが DesktopWindowXamlSource に達したら、UI のナビゲーション順序で最初の Windows.UI.Xaml.UIElement オブジェクトにフォーカスを移動して、ユーザーが要素を順番に移動するのに合わせて以降の Windows.UI.Xaml.UIElement にフォーカスを移動した後、フォーカスを DesktopWindowXamlSource の外に出して親 UI 要素に戻します。

UWP XAML ホスティング API には、これらのタスクを実行するのに役立ついくつかの型とメンバーが用意されています。

  • DesktopWindowXamlSource にキーボード ナビゲーションが入ると、GotFocus イベントが発生します。 このイベントをプログラムで処理し、NavigateFocus メソッドを使用することによって、ホストされている最初の Windows.UI.Xaml.UIElement にフォーカスを移動します。

  • ユーザーが DesktopWindowXamlSource の最後のフォーカス可能な要素にいて、Tab キーまたは方向キーを押すと、TakeFocusRequested イベントが発生します。 このイベントをプログラムで処理し、ホスト アプリケーションで次にフォーカス可能な要素にフォーカスを移動します。 たとえば、DesktopWindowXamlSourceSystem.Windows.Interop.HwndHost でホストされている WPF アプリケーションでは、MoveFocus メソッドを使用して、ホスト アプリケーション内の次にフォーカス可能な要素にフォーカスを移すことができます。

動作するサンプル アプリケーションのコンテキストでこれを行う方法が示されている例については、次のコード ファイルを参照してください。

レイアウトの変更を処理する

ユーザーが親 UI 要素のサイズを変更した場合は、必要なレイアウト変更を処理して、UWP コントロールが意図したとおりに表示されるようにする必要があります。 ここでは、考慮すべき重要なシナリオをいくつか示します。

  • C++ デスクトップ アプリケーションで WM_SIZE メッセージを処理するときは、SetWindowPos 関数を使用して、ホストされている XAML Islands の位置を変更できます。 例については、SampleApp.cpp コード ファイルをご覧ください。

  • DesktopWindowXamlSource でホストしている Windows.UI.Xaml.UIElement に合わせるために必要な四角形の領域のサイズを、親 UI 要素で取得する必要がある場合は、Windows.UI.Xaml.UIElementMeasure メソッドを呼び出します。 たとえば、次のように入力します。

    • WPF アプリケーションでは、DesktopWindowXamlSource をホストしている HwndHostMeasureOverride メソッドから、この操作を行うことができます。 例については、Windows Community Toolkit の WindowsXamlHostBase.Layout.cs ファイルをご覧ください。

    • Windows フォーム アプリケーションでは、DesktopWindowXamlSource をホストしている ControlGetPreferredSize メソッドから、この操作を行うことができます。 例については、Windows Community Toolkit の WindowsXamlHostBase.Layout.cs ファイルをご覧ください。

  • 親 UI 要素のサイズが変更されたときは、DesktopWindowXamlSource でホストしているルート Windows.UI.Xaml.UIElementArrange メソッドを呼び出します。 たとえば、次のように入力します。

    • WPF アプリケーションでは、DesktopWindowXamlSource をホストしている HwndHost オブジェクトの ArrangeOverride メソッドから、この操作を行うことができます。 例については、Windows Community Toolkit の WindowsXamlHost.Layout.cs ファイルをご覧ください。

    • Windows フォーム アプリケーションでは、DesktopWindowXamlSource をホストしている ControlSizeChanged イベントに対するハンドラーから、この操作を行うことができます。 例については、Windows Community Toolkit の WindowsXamlHost.Layout.cs ファイルをご覧ください。

DPI の変更を処理する

UWP XAML フレームワークは、ホストされている UWP コントロールの DPI の変更が自動的に処理されます (たとえば、ユーザーが画面の DPI が異なるモニター間でウィンドウをドラッグした場合)。 最適なエクスペリエンスのためには、Windows フォーム、WPF、または C++ デスクトップ アプリケーションを、モニターごとの DPI に対応するように構成することをお勧めします。

モニターごとの DPI に対応するようにアプリケーションを構成するには、サイド バイ サイド アセンブリ マニフェストをプロジェクトに追加し、<dpiAwareness> 要素を PerMonitorV2 に設定します。 この値について詳しくは、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>