CoreWindow에 의존하는 WinRT UI 개체 표시

특정 선택기, 팝업, 대화 상자 및 기타 WinRT(Windows 런타임) 개체는 CoreWindow에 따라 달라지며, 일반적으로 UI(사용자 인터페이스)를 표시합니다. CoreWindow는 데스크톱 앱에서 지원되지 않지만(Core 지원되지 않는 클래스 참조) 약간의 상호 운용 코드를 추가하여 데스크톱 앱에서 이러한 WinRT 클래스를 많이 사용할 수 있습니다.

데스크톱 앱은 WinUI(Windows UI 라이브러리) 3, WPF(Windows Presentation Foundation) 또는 WinForms(Windows Forms) 앱일 수 있습니다. 코드 예제는 C# 및 C++/WinRT에 표시됩니다.

WinRT UI 개체에 대한 HWND(소유자 창 핸들) 설정

IInitializeWithWindow 인터페이스(또는 해당 IDataTransferManagerInterop 인터페이스)를 구현하는 클래스의 경우 표시하기 전에 해당 인터페이스를 사용하여 개체의 소유자 창을 설정할 수 있습니다. 두 단계 프로세스입니다.

  1. 표시할 UI 개체의 소유자가 될 창을 결정하고 해당 창의 HWND를 검색합니다. 이 단계에 대한 자세한 내용 및 코드 예제는 HWND(창 핸들 검색)를 참조하세요.
  2. 그런 다음 적절한 상호 운용성 API(C# 또는 C++/WinRT)를 호출하여 WinRT UI 개체에 대한 HWND(소유자 창 핸들)를 설정합니다.

IInitializeWithWindow를 구현하는 클래스의 경우

이러한 클래스는 IInitializeWithWindow를 구현합니다.

참고 항목

위의 목록은 반드시 불완전합니다. 형식의 설명서를 참조하여 IInitializeWithWindow(또는 동등한 interop 인터페이스)를 구현하는지 확인합니다.

다음 섹션에는 FolderPicker를 표시하는 코드 예제가 포함되어 있습니다. 그러나 위에 나열된 API를 표시하는 것과 동일한 기술입니다.

C#을 사용하는 WinUI 3(.NET 6 이상이 포함된 WPF/WinForms)

참고 항목

이 섹션의 코드 예제에서는 WinRT.Interop.WindowNative C# interop 클래스를 사용합니다. .NET 6 이상을 대상으로 하는 경우 WPF 또는 WinForms 프로젝트에서 해당 클래스를 사용할 수 있습니다. 이를 위해 프로젝트를 설정하는 방법에 대한 자세한 내용은 .NET 앱에서 interop API 호출을 참조하세요.

아래 C# 코드는 HWND(창 검색 핸들)설명된 패턴을 이미 사용했음을 예상합니다. 그런 다음 표시하려는 UI 개체의 소유자 창을 설정하기 위해 코드는 WinRT.Interop.InitializeWithWindow C# interop 클래스에서 Initialize 메서드를 호출합니다. C# interop 클래스에 대한 자세한 내용은 .NET 앱에서 interop 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# interop 클래스의 RequestVerificationForWindowAsync 메서드를 호출합니다. C# interop 클래스에 대한 자세한 내용은 .NET 앱에서 interop API 호출을 참조 하세요.
  • C++/WinRT. IUserConsentVerifierInterop::RequestVerificationForWindowAsync를 호출합니다.

자세한 정보 및 코드 예제는 UserConsentVerifier를 참조 하세요.

다른 interop 인터페이스를 구현하는 클래스의 경우

이러한 인터페이스에는 HWND(소유자 창 핸들)를 설정할 수 있는 XxxForWindow 메서드가 있습니다. C++/WinRT에서 직접 이러한 인터페이스를 사용할 수 있습니다. 인터페이스 버전은 C# 클래스 형식으로도 존재합니다. 자세한 내용은 .NET 앱에서 interop API 호출을 참조하세요.