某些選擇器、彈出視窗、對話框及其他 Windows 執行時(WinRT)物件依賴 CoreWindow;通常用於顯示使用者介面(UI)。 雖然桌面應用程式不支援 CoreWindow (參見 Core 不支援類別),但你仍可以透過加入一些互通程式碼,在桌面應用程式中使用許多 WinRT 類別。
你的桌面應用程式可以是 WinUI 3、 Windows Presentation Foundation(WPF)或 Windows Forms(WinForms) 應用程式。 程式碼範例以 C# 和 C++/WinRT 呈現。
為 WinRT UI 物件設定擁有者視窗句柄(HWND)
對於實作 IInitializeWithWindow 介面(或等效的 IDataTransferManagerInterop 介面)的類別,你可以利用該介面在物件顯示前設定擁有者視窗。 這是一個兩步驟的過程。
- 決定哪個視窗會是你想顯示的 UI 物件的擁有者,然後取得該視窗的 HWND。 此步驟的更多細節與程式碼範例,請參閱 「擷取視窗handle(HWND)」。
- 接著呼叫適當的互通性 API(適用於 C# 或 C++/WinRT),為 WinRT UI 物件設定擁有者視窗句柄(HWND)。
對於實作 IInitializeWithWindow 的類別
這些類別實作 IInitializeWithWindow:
- Windows.ApplicationModel.Contacts.PinnedContactManager
- Windows.ApplicationModel.Payments.PaymentMediator
- Windows.Devices.Enumeration.DevicePicker
- Windows.Graphics.Capture.GraphicsCapturePicker
- Windows.Media.Casting.CastingDevicePicker
- Windows.Media.DialProtocol.DialDevicePicker
- Windows.Networking.NetworkOperators.ProvisioningAgent
- Windows.Security.Authentication.OnlineId.OnlineIdAuthenticator
- Windows.Services.Store.StoreContext
- Windows.Storage.Pickers.FileOpenPicker
- Windows.Storage.Pickers.FileSavePicker
- Windows.Storage.Pickers.FolderPicker
- Windows.System.FolderLauncherOptions—Windows 10,版本 1903(10.0; Build 18362)及之後
- Windows.System.LauncherOptions—Windows 10,版本 1903(10.0; 編譯18362)及之後
- Windows.UI.Core.CoreWindowDialog
- Windows.UI.Core.CoreWindowFlyout
- Windows.UI.Popups.MessageDialog。 但對於新應用程式,我們建議改用 ContentDialog 控制項。
- Windows.UI.彈出視窗.彈出選單
- Windows.UI.StartScreen.SecondaryTile
- Windows.Web.Http.Filters.HttpBaseProtocolFilter
備註
上述列表必然不完整——請參閱某型別的文件,看看它是否實作了 IInitializeWithWindow (或等效的互操作介面)。
接下來的章節包含用來顯示 資料夾選擇器的程式碼範例。 但顯示上述任何 API 的技術都是一樣的。
WinUI 3 搭配 C#(也支援 WPF/WinForms 搭配 .NET 6 或更新版本)
備註
本節的程式碼範例使用 WinRT.Interop.WindowNative C# 互操作類別。 如果你的目標是 .NET 6 或更新版本,那你可以在 WPF 或 WinForms 專案中使用該類別。 關於如何設定專案來做到這點,請參見「從 .NET 應用程式呼叫互操作 API」。
以下 C# 程式碼預期你已經使用過 Retrieve a window handle (HWND) 中描述的模式。 接著,要設定你想顯示的 UI 物件的擁有者視窗,程式碼會呼叫 WinRT.Interop.InitializeWithWindow C# interop 類別中的 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();
}
WinUI 3 搭配 C++
以下的 C++/WinRT 程式碼預期你已經使用過 Retrieve a window handle (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,如下方程式碼範例所示。
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 方法:
- C#。 呼叫 Windows.Security.Credentials.UI.UserConsentVerifierInterop C# interop 類別的 RequestVerificationForWindowAsync 方法。 想了解更多關於 C# 互通類別的資訊,請參見「從 .NET 應用程式呼叫互操作 API」。
- C++/WinRT。 呼叫 IUserConsentVerifierInterop::RequestVerificationForWindowAsync。
欲了解更多資訊及程式碼範例,請參見 UserConsentVerifier。
對於實作其他互操作介面的類別來說
這些介面有 XxxForWindow 方法,可以設定擁有者視窗句柄(HWND)。 你可以直接從 C++/WinRT 使用這些介面。 介面的版本也以 C# 類別的形式存在——更多細節請參見 「從 .NET 應用程式呼叫互操作 API」。
- IAccountsSettingsPaneInterop
- IDragDropManagerInterop
- IInputPaneInterop
- IPlayToManagerInterop
- IPrintManagerInterop
- IRadialControllerConfigurationInterop
- IRadialControllerIndependentInputSourceInterop
- IRadialControllerInterop
- ISpatialInteractionManagerInterop
- ISystemMediaTransportControlsInterop
- IUIViewSettingsInterop
- IWebAuthenticationCoreManagerInterop