C++/WinRT 是 Windows 运行时 (WinRT) API 的完全标准新式 C++17 语言投影,以基于标头文件的库的形式实现,旨在为你提供对新式 Windows API 的一流访问。 使用 C++/WinRT,可以使用任何符合标准的 C++17 编译器创作和使用Windows 运行时 API。 Windows SDK 包括 C++/WinRT;它已在版本 10.0.17134.0(Windows 10版本 1803 中引入)。
C++/WinRT 是微软推荐用来替代 C++/CX 语言投影和 Windows 运行时 C++ Template Library (WRL) 的方案。 与 C++/WinRT 相关的主题完整列表包含有关与 C++/CX 和 WRL 互操作以及从 C++/CX 和 WRL 迁移的信息。
Important
下面几节介绍了 C++/WinRT 中一些需要重点了解的最重要内容:C++/WinRT 的 SDK 支持 和 Visual Studio 对 C++/WinRT、XAML、VSIX 扩展和 NuGet 包的支持。
另请参阅 “在哪里可以找到 C++/WinRT 示例应用?”。
语言预测
Windows 运行时基于组件对象模型 (COM) API,并且被设计为通过语言投影进行访问。 投影会隐藏 COM 详细信息,并为给定语言提供更自然的编程体验。
Windows 运行时 API 参考内容中的 C++/WinRT 语言投影
浏览Windows 运行时 API 时,单击右上角的语言组合框,然后选择 C++/WinRT 以查看 API 语法块,因为它们显示在 C++/WinRT 语言投影中。
Visual Studio对 C++/WinRT、XAML、VSIX 扩展和 NuGet 包的支持
对于Visual Studio支持,需要Visual Studio 2022、Visual Studio 2019 或 Visual Studio 2017(至少版本 15.6;建议至少为 15.7)。 在Visual Studio安装程序中,安装通用 Windows 平台开发工作负荷。 在安装详细信息>通用 Windows 平台 开发中,如果之前尚未这样做,请勾选 C++ (v14x) 通用 Windows 平台 工具选项。 此外,在Windows设置>隐私和安全(Windows 10:更新和安全性)>对于开发人员,启用开发人员模式选项(Windows 10:而不是旁加载应用选项)。
虽然我们建议使用最新版本的 Visual Studio 和 Windows SDK 进行开发,但如果使用的是与 10.0.17763.0(Windows 10 版本 1809)之前的 Windows SDK 随附的 C++/WinRT 版本,则需至少使用上述Windows命名空间标头Windows 10.0.17134.0(Windows 10版本 1803)项目中的 SDK 目标版本。
Visual Studio 2022 随附了内置 C++/WinRT 项目和项模板,以便你可以立即开始使用 C++/WinRT 开发。 它还随附了适用于 C++/WinRT 投影类型的 Visual Studio 原生调试可视化(natvis),从而提供类似 C# 的调试体验。 Natvis 会在调试版本中自动生效。 有关详细信息,请参阅Visual Studio C++/WinRT 的本机调试可视化效果。
对于较旧版本的 Visual Studio,需要从 Visual Studio 市场下载并安装最新版本的 C++/WinRT Visual Studio 扩展 (VSIX)。
- VSIX 扩展提供 Visual Studio 中的 C++/WinRT 项目和项模板。
- 另外,它还提供 C++/WinRT 投影类型的 Visual Studio 本机调试可视化效果 (natvis)。
以下各节介绍了适用于 C++/WinRT 的Visual Studio项目模板。 使用已安装最新版本的 VSIX 扩展创建新的 C++/WinRT 项目时,新的 C++/WinRT 项目会自动安装 Microsoft.Windows。CppWinRT NuGet 包。 Microsoft.Windows。CppWinRT NuGet 包提供 C++/WinRT 生成支持(MSBuild 属性和目标),使项目在开发计算机和生成代理之间可移植(仅安装 NuGet 包而不是 VSIX 扩展)。
或者,你可以通过手动安装 Microsoft.Windows.CppWinRT NuGet 包来转换现有项目。 安装 (或更新到) 最新版本的 VSIX 扩展后,在 Visual Studio 中打开现有project,单击Project>Manage NuGet 包...>浏览、键入或粘贴 Microsoft.Windows。搜索框中的 CppWinRT,选择搜索结果中的项,然后单击“安装”以安装该project的包。 添加包后,你将获得对项目的 C++/WinRT MSBuild 支持,包括调用 cppwinrt.exe 该工具。
Important
如果你有一些项目是使用早于 1.0.190128.4 的 VSIX 扩展版本创建的(或已升级为可与该版本配合使用),请参阅 VSIX 扩展的早期版本。 该部分包含有关项目配置的重要信息,需要了解这些配置才能使用最新版本的 VSIX 扩展。
- 由于 C++/WinRT 使用 C++17 标准中的功能,因此 NuGet 包在 Visual Studio中设置项目属性 C/C++>Language>C++ Language Standard>
- 它还添加了 /bigobj 编译器选项。
- 它添加 /await 编译器选项以启用
co_await。 - 它指示 XAML 编译器生成 C++/WinRT 代码。
- 你可能还会考虑设置 符合性模式:是 (/permissive-),这会进一步约束你的代码,使其符合标准。
- 要注意的另一个项目属性是 C/C++>常规>将警告视为错误。 将此设置为 “是”(/WX) 或 “否”(/WX-) 以品尝。 有时,工具生成的
cppwinrt.exe源文件会生成警告,直到向它们添加实现为止。
按照上文所述设置系统后,你将能够在Visual Studio中创建和生成或打开 C++/WinRT 项目,并将其部署。
从 2.0 版本开始,Microsoft.Windows.CppWinRT NuGet 包包含 cppwinrt.exe工具。 可以将 cppwinrt.exe 工具指向 Windows 运行时元数据 (.winmd) 文件,以便生成基于标头文件且可投影 API 的标准 C++ 库,详见“在 C++/WinRT 代码中使用的元数据”。 Windows 运行时元数据(.winmd)文件提供了描述Windows 运行时 API 图面的规范方式。 将 cppwinrt.exe 指向元数据后,您可以生成一个库,用于任何在第二方或第三方 Windows 运行时 组件中实现的运行时类,或者在您自己的应用程序中实现的运行时类。 有关详细信息,请参阅 使用 C++/WinRT 的 API。
使用 C++/WinRT,还可以使用标准 C++ 实现自己的运行时类,而无需使用 COM 样式编程。 对于运行时类,只需在 IDL 文件中描述你的类型,midl.exe 和 cppwinrt.exe 就会为你生成实现样板源代码文件。 或者,可以通过从 C++/WinRT 基类派生来实现接口。 有关详细信息,请参阅 使用 C++/WinRT 创作 API。
有关通过项目属性设置的 cppwinrt.exe 工具的自定义选项列表,请参阅 Microsoft.Windows.CppWinRT NuGet 包的自述文件。
你可以通过项目中安装了 Microsoft.Windows.CppWinRT NuGet 包这一点,来识别使用 C++/WinRT MSBuild 支持的项目。
下面是 VSIX 扩展提供的Visual Studio项目模板。
空白应用 (C++/WinRT)
具有 XAML 用户界面的通用 Windows 平台 (UWP)应用的项目模板。 对于 WinUI 3 桌面应用,请改用 Blank App, Packaged (WinUI 3 in Desktop) 模板。
Visual Studio 提供了 XAML 编译器支持,用于从每个 XAML 标记文件后面的接口定义语言 (IDL) (.idl) 文件生成实现和标头存根。 在 IDL 文件中,定义要在应用的 XAML 页面中引用的任何本地运行时类,然后在其中生成一次项目以生成实现模板 Generated Files,并在其中 Generated Files\sources生成存根类型定义。 然后,使用这些存根类型定义进行引用来实现本地运行时类。 请参阅将运行时类分解为 Midl 文件(.idl)。
Visual Studio 中针对 C++/WinRT 的 XAML 设计界面支持已接近 C# 的水平。 在Visual Studio中,可以使用“属性”窗口的“事件”选项卡在 C++/WinRT 项目中添加事件处理程序。 还可以手动将事件处理程序添加到代码 - 有关详细信息,请参阅 使用 C++/WinRT 中的委托处理事件 。
核心应用 (C++/WinRT)
不使用 XAML 的通用 Windows 平台 (UWP)应用的项目模板。 此模板没有 WinUI 3 等效项。
相反,它使用针对 Windows.ApplicationModel.Core 命名空间的 C++/WinRT Windows 命名空间头文件。 生成并运行后,单击空白区域以添加彩色正方形;然后单击彩色正方形以拖动它。
Windows 控制台应用程序 (C++/WinRT)
适用于 Windows Desktop 的 C++/WinRT 客户端应用程序的项目模板,带有控制台用户界面。
Windows 桌面应用程序 (C++/WinRT)
适用于 Windows 桌面的 C++/WinRT 客户端应用程序项目模板,用于在 Win32 MessageBox 中显示 Windows 运行时 Windows.Foundation.Uri。
Windows 运行时组件 (C++/WinRT)
用于组件的项目模板;通常供通用 Windows 平台 (UWP) 使用。
此模板演示了 midl.exe>cppwinrt.exe 工具链,即先根据 IDL 生成 Windows 运行时 元数据(.winmd),再根据 Windows 运行时 元数据生成实现存根和头文件存根。
在 IDL 文件中,定义组件中的运行时类、其默认接口及其实现的任何其他接口。 将项目构建一次,以生成 module.g.cpp、module.h.cpp、Generated Files 中的实现模板,以及 Generated Files\sources 中的存根类型定义。 然后使用这些存根类型定义进行引用,以便在组件中实现运行时类。 请参阅将运行时类分解为 Midl 文件(.idl)。
将生成的 Windows 运行时组件二进制文件及其 .winmd 与使用它们的 UWP 应用绑定。
VSIX 扩展的早期版本
建议安装 (或更新到) 最新版本的 VSIX 扩展。 它配置为默认更新自身。 如果这样做,并且具有使用早于 1.0.190128.4 的 VSIX 扩展版本创建的项目,则本部分包含有关升级这些项目以使用新版本的重要信息。 如果未更新,仍会在本节中找到有用的信息。
对于受支持的 Windows SDK 和 Visual Studio 版本以及 Visual Studio 配置,上文 Visual Studio 对 C++/WinRT、XAML、VSIX 扩展和 NuGet 包的支持 一节中的信息同样适用于较早版本的 VSIX 扩展。 以下信息描述了与使用早期版本创建或升级为使用的项目的行为和配置的重要差异。
创建时间早于 1.0.181002.2
如果项目是使用低于 1.0.181002.2 的 VSIX 扩展版本创建的,则 C++/WinRT 生成支持已内置到该版本的 VSIX 扩展中。 您的项目已在.vcxproj文件中设置了<CppWinRTEnabled>true</CppWinRTEnabled>属性。
<Project ...>
<PropertyGroup Label="Globals">
<CppWinRTEnabled>true</CppWinRTEnabled>
...
可以通过手动安装 Microsoft.Windows.CppWinRT NuGet 包来升级项目。 安装(或升级到)最新版本的 VSIX 扩展后,在 Visual Studio 中打开项目,依次单击 Project>Manage NuGet Packages...>Browse,在搜索框中键入或粘贴 Microsoft.Windows.CppWinRT,在搜索结果中选择该项,然后单击 Install,为项目安装该包。
使用介于 1.0.181002.2 和 1.0.190128.3 之间的版本创建(或升级到)
如果项目是使用 1.0.181002.2 和 1.0.190128.3(含)的 VSIX 扩展版本创建的,则Microsoft.Windows。CppWinRT NuGet 包由项目模板自动安装在项目中。 你可能还升级了较旧的项目,以在此范围内使用 VSIX 扩展的版本。 如果你这样做了,那么由于这一范围内的 VSIX 扩展版本仍提供生成支持,升级后的项目可能安装了,也可能没有安装 Microsoft.Windows.CppWinRT NuGet 包。
若要升级项目,请按照上一节中的说明进行操作,并确保项目中已安装 Microsoft.Windows.CppWinRT NuGet 包。
升级配置无效
在最新版本的 VSIX 扩展中,如果某个项目具有 <CppWinRTEnabled>true</CppWinRTEnabled> 属性,则它也必须安装 Microsoft.Windows.CppWinRT NuGet 包,否则该属性无效。 具有此配置的项目生成错误消息“C++/WinRT VSIX 不再提供项目生成支持。 请向 Microsoft.Windows.CppWinRT NuGet 包添加项目引用。
如上所述,C++/WinRT 项目现在需要在其中安装 NuGet 包。
由于该 <CppWinRTEnabled> 元素现已过时,因此可以选择编辑 .vcxproj和删除该元素。 这不是绝对必要的,但它是一个选项。
此外,如果 .vcxproj 包含 <RequiredBundles>$(RequiredBundles);Microsoft.Windows.CppWinRT</RequiredBundles>,则可以将其删除,以便无需安装 C++/WinRT VSIX 扩展即可生成。
对 C++/WinRT 的 SDK 支持
尽管目前仅出于兼容性原因,但从版本 10.0.17134.0(Windows 10 版本 1803 开始),Windows SDK 包含一个基于头文件的标准 C++ 库,用于使用第一方Windows API(Windows命名空间中的Windows 运行时 API)。 这些标头位于文件夹 %WindowsSdkDir%Include<WindowsTargetPlatformVersion>\cppwinrt\winrt内。 从 Windows SDK 版本 10.0.17763.0(Windows 10 版本 1809)起,这些标头会在项目的 $(GeneratedFilesDir) 文件夹中生成。
同样是出于兼容性考虑,Windows SDK 也随附了 cppwinrt.exe 工具。 但是,我们建议你改为安装并使用最新版本的 cppwinrt.exe,该版本包含在 Microsoft.Windows.CppWinRT NuGet 包中。 该包和 cppwinrt.exe 已在上述章节中进行了说明。
C++/WinRT 投影中的自定义类型
在 C++/WinRT 编程中,可以使用标准 C++ 语言功能和 标准 C++ 数据类型和 C++/WinRT,包括一些 C++ 标准库数据类型。 但是,你还将了解投影中的一些自定义数据类型,你可以选择使用它们。 例如,我们在 C++/WinRT 入门中的快速入门代码示例中使用 winrt::hstring。
winrt::com_array 是另一种你迟早会用到的类型。 但不太可能直接使用 winrt::array_view 等类型。 或者,可以选择不使用它,以便在 C++ 标准库中出现等效类型时,你不会更改任何代码。
Warning
如果仔细研究 C++/WinRT Windows命名空间标头,还可能会看到这些类型。 例如 winrt::param::hstring,不过也有集合方面的示例。 它们只是为了优化输入参数的绑定,它们会产生很大的性能改进,并使大多数调用模式“仅有效”用于相关的标准 C++ 类型和容器。 在增加最大价值的情况下,这些类型只被投影使用过。 它们经过高度优化,不适合常规使用;不要想自己使用它们。 也不应使用命名空间中的任何 winrt::impl 内容,因为这些是实现类型,因此可能会更改。 应继续使用标准类型或 winrt 命名空间中的类型。
另请参阅 将参数传递到 ABI 边界。