CoreWindow に依存する WinRT UI オブジェクトを表示する

特定のピッカー、ポップアップ、ダイアログ、およびその他の Windows ランタイム (WinRT) オブジェクトは、一般的にユーザー インターフェイス (UI) を表示するために CoreWindow に依存します。 CoreWindow はデスクトップ アプリではサポートされていませんが (コアサポートされていないクラスを参照)、少し相互運用コードを追加することで、デスクトップ アプリでこれらの WinRT クラスの多くを使用できます。

デスクトップ アプリには、Windows UI ライブラリ (WinUI) 3Windows Presentation Foundation (WPF)、または Windows フォーム (WinForms) アプリを使用できます。 コード例は、C# と C++/WinRT で示されています。

WinRT UI オブジェクトの所有者ウィンドウ ハンドル (HWND) を設定する

IInitializeWithWindow インターフェイス (または同等の IDataTransferManagerInterop インターフェイス) を実装するクラスの場合は、そのインターフェイスを使用して、オブジェクトを表示する前に所有者ウィンドウを設定できます。 これは 2 段階のプロセスです。

  1. 表示する UI オブジェクトの所有者になるウィンドウを決定し、そのウィンドウの HWND を取得します。 この手順の詳細とコード例については、「ウィンドウ ハンドルの取得 (HWND)」を参照してください
  2. 次に、適切な相互運用機能 API (C# または C++/WinRT の場合) を呼び出して、WinRT UI オブジェクトの所有者ウィンドウ ハンドル (HWND) を設定します。

IInitializeWithWindow を実装するクラスの場合

これらのクラスは、IInitializeWithWindow を実装します。

Note

上記の一覧は必ずしも不完全です。型のドキュメントを参照して、IInitializeWithWindow (または同等の相互運用インターフェイス) を実装しているかどうかを確認してください。

次のセクションには、FolderPicker を表示するコード例が含まれています ただし、上記の API のいずれかを表示するのと同じ手法です。

C# を使用した WinUI 3 (.NET 6 以降の WPF/WinForms も含む)

Note

このセクションのコード例では、 WinRT.Interop.WindowNative C# 相互運用クラスを使用します。 .NET 6 以降を対象とする場合は、WPF または WinForms プロジェクトでそのクラスを使用できます。 これを行うためにプロジェクトを設定する方法については、「.NET アプリから相互運用 API を呼び出す」を参照してください

次の C# コードは、「ウィンドウ ハンドルの取得 (HWND)」に記載されているパターンを既に使用していることを想定しています。 次に、表示する UI オブジェクトの所有者ウィンドウを設定するために、コードは WinRT.Interop.InitializeWithWindow C# 相互運用クラスの Initialize メソッドを呼び出します。 C# 相互運用クラスの詳細については、「.NET アプリからの相互運用 API の呼び出し」を参照してください

// MainWindow.xaml.cs
private async void ShowFolderPickerAsync(IntPtr hWnd)
{
    // Create a folder picker.
    var folderPicker = new Windows.Storage.Pickers.FolderPicker();

    // Initialize the folder picker with the window handle (HWND).
    WinRT.Interop.InitializeWithWindow.Initialize(folderPicker, hWnd);

    // Use the folder picker as usual.
    folderPicker.FileTypeFilter.Add("*");
    var folder = await folderPicker.PickSingleFolderAsync();
}

C++ での WinUI 3

以下の C++/WinRT コードは、「ウィンドウ ハンドルの取得 (HWND)」に記載されているパターンを既に使用していることを想定しています。 次に、表示する UI オブジェクトの所有者ウィンドウを設定するために、コードは相互運用機能メソッド IInitializeWithWindow::Initialize を呼び出します。

// pch.h
...
#include <microsoft.ui.xaml.window.h>
#include <Shobjidl.h>
#include <winrt/Windows.Storage.Pickers.h>

// MainWindow.xaml.cpp
winrt::fire_and_forget ShowFolderPickerAsync(HWND hWnd)
{
    // Create a folder picker.
    Windows::Storage::Pickers::FolderPicker folderPicker;

    // Initialize the folder picker with the window handle (HWND).
    auto initializeWithWindow{ folderPicker.as<::IInitializeWithWindow>() };
    initializeWithWindow->Initialize(hWnd);

    // Use the folder picker as usual.
    folderPicker.FileTypeFilter().Append(L"*");
    auto folder{ co_await folderPicker.PickSingleFolderAsync() };
}

IDataTransferManagerInterop を実装するクラスの場合

Windows.ApplicationModel.DataTransfer.DataTransferManager クラスは、IDataTransferManagerInterop インターフェイスを実装します (IInitializeWithWindow と同様に、所有者ウィンドウを設定できます)。

デスクトップ アプリでは、DataTransferManager.ShowShareUI メソッドを呼び出す代わりに、次のコード例に示すように IDataTransferManagerInterop::ShowShareUIForWindow を呼び出します。

C# を使用した WinUI 3 (.NET 6 以降の WPF/WinForms も含む)

// MainWindow.xaml.cs
...
public sealed partial class MainWindow : Window
{
    ...

    [System.Runtime.InteropServices.ComImport]
    [System.Runtime.InteropServices.Guid("3A3DCD6C-3EAB-43DC-BCDE-45671CE800C8")]
    [System.Runtime.InteropServices.InterfaceType(
        System.Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)]
    interface IDataTransferManagerInterop
    {
        IntPtr GetForWindow([System.Runtime.InteropServices.In] IntPtr appWindow,
            [System.Runtime.InteropServices.In] ref Guid riid);
        void ShowShareUIForWindow(IntPtr appWindow);
    }

    static readonly Guid _dtm_iid = 
        new Guid(0xa5caee9b, 0x8708, 0x49d1, 0x8d, 0x36, 0x67, 0xd2, 0x5a, 0x8d, 0xa0, 0x0c);

    private void myButton_Click(object sender, RoutedEventArgs e)
    {
        // Retrieve the window handle (HWND) of the current WinUI 3 window.
        var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

        IDataTransferManagerInterop interop =
        Windows.ApplicationModel.DataTransfer.DataTransferManager.As
            <IDataTransferManagerInterop>();

        IntPtr result = interop.GetForWindow(hWnd, _dtm_iid);
        var dataTransferManager = WinRT.MarshalInterface
            <Windows.ApplicationModel.DataTransfer.DataTransferManager>.FromAbi(result);

        dataTransferManager.DataRequested += (sender, args) =>
        {
            args.Request.Data.Properties.Title = "In a desktop app...";
            args.Request.Data.SetText("...display WinRT UI objects that depend on CoreWindow.");
            args.Request.Data.RequestedOperation = 
                Windows.ApplicationModel.DataTransfer.DataPackageOperation.Copy;
        };

        // Show the Share UI
        interop.ShowShareUIForWindow(hWnd);
    }
}
...

C++ での WinUI 3

// pch.h in a Windows App SDK app
...
#include <shobjidl_core.h>
#include <microsoft.ui.xaml.window.h>
#include <winrt/Windows.ApplicationModel.DataTransfer.h>
...

// MainWindow.xaml.cpp
...
void MainWindow::myButton_Click(IInspectable const&, RoutedEventArgs const&)
{
    // Retrieve the window handle (HWND) of the current WinUI 3 window.
    auto windowNative{ this->m_inner.as<::IWindowNative>() };
    HWND hWnd{ 0 };
    windowNative->get_WindowHandle(&hWnd);

    winrt::com_ptr<IDataTransferManagerInterop> interop = 
        winrt::get_activation_factory<Windows::ApplicationModel::DataTransfer::DataTransferManager,
        IDataTransferManagerInterop>();

    winrt::guid _dtm_iid{ 0xa5caee9b, 0x8708, 0x49d1, { 0x8d, 0x36, 0x67, 0xd2, 0x5a, 0x8d, 0xa0, 0x0c } };
    Windows::ApplicationModel::DataTransfer::DataTransferManager dataTransferManager{ nullptr };
    interop->GetForWindow(hWnd, _dtm_iid, winrt::put_abi(dataTransferManager));

    dataTransferManager.DataRequested([](Windows::ApplicationModel::DataTransfer::DataTransferManager const& /* sender */,
        Windows::ApplicationModel::DataTransfer::DataRequestedEventArgs const& args)
    {
        args.Request().Data().Properties().Title(L"In a desktop app...");
        args.Request().Data().SetText(L"...display WinRT UI objects that depend on CoreWindow.");
        args.Request().Data().RequestedOperation(Windows::ApplicationModel::DataTransfer::DataPackageOperation::Copy);
    });

    interop->ShowShareUIForWindow(hWnd);
}
...

IUserConsentVerifierInterop を実装するクラスの場合

Windows.Security.Credentials.UI.UserConsentVerifier クラスは、IUserConsentVerifierInterop インターフェイスを実装します (IInitializeWithWindow のように、所有者ウィンドウを設定できます)。

デスクトップ アプリでは、UserConsentVerifier.RequestVerificationAsync メソッドを呼び出す代わりに、次の操作を行います。

  • C#Windows.Security.Credentials.UI.UserConsentVerifierInterop C# 相互運用クラスの RequestVerificationForWindowAsync メソッドを呼び出します。 C# 相互運用クラスの詳細については、「.NET アプリからの相互運用 API の呼び出し」を参照してください
  • C++/WinRT。 IUserConsentVerifierInterop::RequestVerificationForWindowAsync を呼び出 します

詳細とコード例については、「UserConsentVerifier」を参照してください

他の相互運用インターフェイスを実装するクラスの場合

これらのインターフェイスには XxxForWindow メソッドがあり、所有者ウィンドウ ハンドル (HWND) を設定できます。 これらのインターフェイスは、C++/WinRT から直接使用できます。 インターフェイスのバージョンも C# クラスの形式で存在します。詳細については、「.NET アプリからの相互運用 API の呼び出し」を参照してください