从 .NET 5+ 应用调用互操作 API

作为 C# 桌面应用程序开发者,在 .NET 5 和更高版本中,你可以利用表示若干互操作函数和 Windows 运行时 (WinRT) COM 互操作界面的 C# 互操作类。 这其中包括表示 IWindowNativeIInitializeWithWindowGetWindowIdFromWindow 函数等的 C# 类。

该主题列出了可用的 C# 互操作类,并演示如何使用它们。 该主题末尾的背景部分介绍了互操作接口在 .NET 之前版本中的使用方式,以及更改的原因。

配置 .NET 5+ 桌面项目以使用 C# 互操作类

下一部分(可用 C# 互操作类)中列出的 C# 互操作类适用于 .NET 5 和更高版本,方法是作为 Windows 应用 SDK 的一部分,或通过使用特定目标框架名字对象,后面部分会进行介绍。

在 WinUI 3 C# 桌面项目中

在 Visual Studio 中创建新的 WinUI 3 项目时(请参阅创建你的第一个 WinUI 3 项目),项目已配置,你可立即开始使用所有 C# 互操作类。

在其他 C# 桌面项目类型(WPF 或 WinForms)中

对于其他 .NET 5+ 桌面项目类型(例如 Windows Presentation Foundation (WPF)Windows 窗体 (WinForms)),你需要先配置项目,然后才能访问 C# 互操作类。 对于下面列出的第一组类,需要引用 Windows 应用 SDK。 对于第二个集,需要配置面向 Windows 10 版本 1809 或更高版本的目标框架名字对象,如下所示:

  1. 打开 C# .NET 5+ 桌面项目的项目文件。

  2. .csproj 文件中,修改 TargetFramework 元素以面向特定的 .NET 和 Windows SDK 版本。 例如,以下元素适用于面向 Windows 10 版本 2004 的 .NET 6 项目。

    <PropertyGroup>
      <TargetFramework>net6.0-windows10.0.19041.0</TargetFramework>
    </PropertyGroup>
    

有关详细信息(包括其他受支持值的列表),请参阅使用“目标框架名字对象”选项

可用的 C# 互操作类

注意

以下类需要 .NET 5.0.205 SDK 或更高版本。

下面是可用的 C# 互操作类,它们从其基础互操作函数或 WinRT COM 互操作接口映射。 列出的每个类都实现了其基础互操作 API 的函数/方法,并为参数和返回值提供了类型安全的包装器。 例如, Windows.ApplicationModel.DataTransfer.DragDrop.Core.DragDropManagerInterop.GetForWindow 需要 IntPtr 窗口句柄 (HWND)参数并返回 CoreDragDropManager 对象。 下面的所有 C# 互操作类和关联的方法都是静态的。

作为 Windows 应用 SDK 的一部分提供

Microsoft.UI.Win32Interop 类实现下表中的 C# 互操作方法。 有关代码示例,请参阅管理应用窗口

互操作函数 C# 互操作方法
GetDisplayIdFromMonitor (Microsoft.UI) DisplayId Win32Interop.GetDisplayIdFromMonitor(IntPtr hmonitor)
GetIconFromIconId (Microsoft.UI) IntPtr Win32Interop.GetIconFromIconId(IconId iconId)
GetIconIdFromIcon (Microsoft.UI) IconId Win32Interop.GetIconIdFromIcon(IntPtr hicon)
GetMonitorFromDisplayId (Microsoft.UI) IntPtr Win32Interop.GetMonitorFromDisplayId(DisplayId displayId)
GetWindowFromWindowId (Microsoft.UI) IntPtr Win32Interop.GetWindowFromWindowId(WindowId windowId)
GetWindowIdFromWindow (Microsoft.UI) WindowId Win32Interop.GetWindowIdFromWindow(IntPtr hwnd)

通过目标框架名字对象提供

WinRT COM 互操作接口 C# 互操作类
IAccountsSettingsPaneInterop (Windows.UI.ApplicationSettings) AccountsSettingsPaneInterop
IDragDropManagerInterop (Windows.ApplicationModel.DataTransfer.DragDrop.Core) DragDropManagerInterop
IInitializeWithWindow (WinRT.Interop) InitializeWithWindow
IInputPaneInterop (Windows.UI.ViewManagement) InputPaneInterop
IPlayToManagerInterop (Windows.Media.PlayTo) PlayToManagerInterop
IPrintManagerInterop (Windows.Graphics.Printing) PrintManagerInterop
IRadialControllerConfigurationInterop (Windows.UI.Input) RadialControllerConfigurationInterop
IRadialControllerIndependentInputSourceInterop (Windows.UI.Input.Core) RadialControllerIndependentInputSourceInterop
IRadialControllerInterop (Windows.UI.Input) RadialControllerInterop
ISpatialInteractionManagerInterop (Windows.UI.Input.Spatial) SpatialInteractionManagerInterop
ISystemMediaTransportControlsInterop (Windows.Media) SystemMediaTransportControlsInterop
IUIViewSettingsInterop (Windows.UI.ViewManagement) UIViewSettingsInterop
IUserConsentVerifierInterop (Windows.Security.Credentials.UI) UserConsentVerifierInterop
IWebAuthenticationCoreManagerInterop (Windows.Security.Authentication.Web.Core) WebAuthenticationCoreManagerInterop
IWindowNative 仅限 WinUI 3

(WinRT.Interop) WindowNative

有关 WPF 和 WinForms 的替代方法,请参阅检索窗口句柄 (HWND)

代码示例

此代码示例演示了如何在 WinUI 3 应用程序中使用其中两个 C# 互操作类(请参阅创建你的第一个 WinUI 3 项目)。 示例场景是显示 Windows.Storage.Pickers.FolderPicker。 但在桌面应用中显示选取器之前,需要先使用所有者窗口的句柄 (HWND) 将其初始化。

  1. 可以使用 IWindowNative WinRT COM 互操作接口获取窗口句柄 (HWND)。 (查看上一部分中的表)该接口由 WinRT.Interop.WindowNative C# 互操作类表示。 此处,this 对象是对来自主窗口代码隐藏文件的 Microsoft.UI.Xaml.Window 对象的引用。
  2. 若要使用所有者窗口初始化一段 UI,请使用 IInitializeWithWindow WinRT COM 互操作界面。 该接口由 WinRT.Interop.InitializeWithWindow C# 互操作类表示。
private async void myButton_Click(object sender, RoutedEventArgs e)
{
    // Create a folder picker.
    var folderPicker = new Windows.Storage.Pickers.FolderPicker();

    // 1. Retrieve the window handle (HWND) of the current WinUI 3 window.
    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

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

另请参阅检索窗口句柄 (HWND)显示依赖于 CoreWindow 的 WinRT UI 对象

背景

以前版本的 .NET Framework 和 .NET Core 有 WinRT 的内置知识。 对于这些以前版本,你可以直接以 C# 定义具有 ComImport 特性的互操作接口,并将投影类直接强制转换为该互操作接口。

由于 WinRT 是一种特定于 Windows 的技术,为了支持 .NET 5 的可移植性和效率目标,我们从 C# 编译器和 .NET 运行时中移出了 WinRT 保护支持,将其移动到 C#/WinRT 工具包(请参阅对 WinRT 的内置支持已从 .NET 移出)。

尽管 ComImport 技术仍适用于基于 IUnknown的互操作接口,但它已不再适用于基于 IInspectable 的接口;这种接口用于与 WinRT 进行互操作。

因此,作为替换,在 .NET 5 及更高版本中,可以使用本主题中所述的 C# 互操作类。

故障排除和已知问题

C# 互操作类当前没有已知问题。 若要提供反馈或报告其他问题,请在 WindowsAppSDK GitHub 存储库中添加对现有问题的反馈或提出新问题。