Отображение объектов пользовательского интерфейса WinRT, зависящих от CoreWindow

Определенные средства выбора, всплывающие окна, диалоговые окна и другие объекты среды выполнения Windows (WinRT) зависят от CoreWindow; обычно для вывода пользовательского интерфейса (UI). Несмотря на то, что CoreWindow не поддерживается в классических приложениях (см . неподдерживаемые классы Core), вы по-прежнему можете использовать многие из этих классов WinRT в классическом приложении, добавив немного кода взаимодействия.

Классическое приложение может быть приложением Windows UI Library (WinUI) 3, Windows Presentation Foundation (WPF) или Windows Forms (WinForms). Примеры кода представлены в C# и C++/WinRT.

Установка дескриптора окна владельца (HWND) для объекта пользовательского интерфейса WinRT

Для классов, реализующих интерфейс IInitializeWithWindow (или эквивалентный интерфейс IDataTransferManagerInterop ), этот интерфейс можно использовать для задания окна владельца объекта перед отображением. Этот процесс состоит из двух этапов.

  1. Определите, какое окно будет владельцем объекта пользовательского интерфейса, который вы хотите отобразить, и получите HWND этого окна. Дополнительные сведения и примеры кода для этого шага см. в разделе "Получение дескриптора окна" (HWND).
  2. Затем вызовите соответствующий API взаимодействия (для C# или C++/WinRT), чтобы задать дескриптор окна владельца (HWND) для объекта пользовательского интерфейса WinRT.

Для классов, реализующих IInitializeWithWindow

Эти классы реализуют IInitializeWithWindow:

Примечание.

Приведенный выше список обязательно является неполным— ознакомьтесь с документацией типа, чтобы узнать, реализует ли он IInitializeWithWindow (или эквивалентный интерфейс взаимодействия).

В следующих разделах содержатся примеры кода для отображения FolderPicker. Но это тот же способ отображения любого из API, перечисленных выше.

WinUI 3 с C# (также WPF/WinForms с .NET 6 или более поздней версии)

Примечание.

Примеры кода в этом разделе используют класс взаимодействия WinRT.Interop.WindowNative C#. Если вы используете .NET 6 или более поздней версии, этот класс можно использовать в проекте WPF или WinForms. Сведения о настройке проекта для этого см. в разделе API взаимодействия вызовов из приложения .NET.

Приведенный ниже код C# ожидает, что вы уже использовали шаблон, описанный в обработчике окна (HWND). Затем, чтобы задать окно владельца для объекта пользовательского интерфейса, который требуется отобразить, код вызывает метод Initialize в классе взаимодействия WinRT.Interop.InitializeWithWindow C#. Дополнительные сведения о классах взаимодействия C# см. в разделе API взаимодействия вызовов из приложения .NET.

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

WinUI 3 с C++

Приведенный ниже код C++/WinRT ожидает, что вы уже использовали шаблон, документированный в дескрипторе окна (HWND). Затем, чтобы задать окно владельца для объекта пользовательского интерфейса, который требуется отобразить, код вызывает метод взаимодействия 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, как показано в примерах кода ниже.

WinUI 3 с C# (также WPF/WinForms с .NET 6 или более поздней версии)

// 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);
    }
}
...

WinUI 3 с C++

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

Дополнительные сведения и примеры кода см. в разделе UserConsentVerifier.

Для классов, реализующих другие интерфейсы взаимодействия

Эти интерфейсы имеют методы XxxForWindow , которые позволяют задать дескриптор окна владельца (HWND). Эти интерфейсы можно использовать непосредственно из C++/WinRT. Версии интерфейсов также существуют в виде классов C#. Дополнительные сведения см. в разделе API взаимодействия вызовов из приложения .NET.