顯示相依於 CoreWindow 的 WinRT UI 物件

特定選擇器、快顯視窗、對話方塊和其他 Windows 執行階段 (WinRT) 物件均相依於 CoreWindow,通常用於顯示使用者介面 (UI)。 即使傳統型應用程式不支援 CoreWindow (請參閱Core 不支援類別),您仍可以通過新增一些交互操作程式碼在傳統型應用程式中使用其中許多 WinRT 類別。

您的傳統型應用程式可以是 Windows UI 程式庫 (WinUI) 3Windows Presentation Foundation (WPF)Windows Forms (WinForms) 應用程式。 程式碼範例會以 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 方法:

如需詳細資訊和程式碼範例,請參閱 UserConsentVerifier

若為實作其他 Interop 介面的類別

這些介面具有 XxxForWindow 方法,可讓您設定擁有者視窗控制代碼 (HWND)。 您可以直接從 C++/WinRT 使用這些介面。 介面的版本也以 C# 類別的形式存在,如需詳細資訊,請參閱從 .NET 應用程式呼叫 Interop API