Windows 运行时 C++ 模板库 (WRL) 是一个提供低级别方式来创作和使用 Windows运行时组件的模板库。
WRL 现在已由 C++/WinRT 取代。C++/WinRT 是 Windows 运行时 API 的标准 C++17 语言投影。 从版本 1803 (10.0.17134.0) 起,C++/WinRT 在 Windows SDK 中提供。 C++/WinRT 完全在头文件中实现,旨在提供对新式 Windows API 的优先访问权限。
通过 C++/WinRT,可以使用任何符合标准的 C++17 编译器来同时使用和创作 Windows 运行时 API。 与适用于 Windows 运行时的任何其他语言选择相比,通常 C++/WinRT 的表现更好,生成的二进制文件更小。 我们将继续支持 C++/CX 和 WRL,但强烈建议新应用程序使用 C++/WinRT。
Windows 运行时 C++ 模板库使你能够更轻松地实现和使用组件对象模型 (COM) 组件。 它提供引用计数这类管理技术来管理对象的生存期,并可通过测试 HRESULT 值来确定操作是否成功。 若要成功使用 Windows 运行时 C++ 模板库,必须认真遵循这些规则和方法。
C++/CX 是一种使用 Windows 运行时组件的基于语言的高级方式。 Windows 运行时 C++ 模板库和 C++/CX 都通过代表你自动执行管护任务来简化 Windows 运行时代码的编写。
Windows 运行时 C++ 模板库和 C++/CX 提供不同的优势。 下面是你可能想要使用 Windows 运行时 C++ 模板库而不是 C++/CX 的部分原因:
Windows 运行时 C++ 模板库在 Windows 运行时应用程序二进制接口 (ABI) 上添加了少量的抽象,使你能够控制基础代码以更好地创建或使用 Windows 运行时 API。
C++/CX 将 COM HRESULT 值表示为异常。 如果你继承了使用 COM 或不使用异常的代码库,可能会发现 Windows 运行时 C++ 模板库可以更自然地与 Windows 运行时配合工作,因为你不必使用异常。
Windows 运行时 C++ 模板库使用 HRESULT 值且不引发异常。 此外,Windows 运行时 C++ 模板库还使用智能指针和 RAII 模式,以帮助确保在应用程序代码引发异常时正确销毁对象。 有关智能指针和 RAII 的详细信息,请参阅智能指针和对象拥有资源 (RAII)。
Windows 运行时 C++ 模板库的用途和设计是由活动模板库 (ATL) 创作而来。活动模板库是一组基于模板的 C++ 类,可以简化编程 COM 对象。 由于 Windows 运行时 C++ 模板库使用标准 C++ 来包装 Windows 运行时,因此你可以更轻松地将许多以 ATL 编写的现有 COM 组件移植到 Windows 运行时并与之交互。 如果你已了解 ATL,可能会发现 Windows 运行时 C++ 模板库编程更容易。
激活和使用 Windows 运行时组件
以下步骤使用 Windows::Foundation::IUriRuntimeClass 接口演示如何为 Windows 运行时组件创建激活工厂、创建该组件的实例以及检索属性值。 它们还演示如何初始化 Windows 运行时。
// 1. 包括 (#include) 任何所需的 Windows 运行时、Windows 运行时 C++ 模板库
// 或 C++ 标准库头文件。#include <Windows.Foundation.h>
#include <wrl\wrappers\corewrappers.h>
#include <wrl\client.h>
#include <stdio.h>using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
// 我们建议您在 .cpp 文件中使用 using namespace 指令使代码更具可读性。// 2. 初始化应用执行所在的线程。 每个应用都必须初始化其线程和线程模型。
// 此示例使用 Microsoft::WRL::Wrappers::RoInitializeWrapper 类初始化 Windows 运行时,
// 并将 RO_INIT_MULTITHREADED 指定为线程模型。
// RoInitializeWrapper 类在构造时调用 Windows::Foundation::Initialize,
// 销毁时调用 Windows::Foundation::Uninitialize。// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
if (FAILED(initialize))
{return PrintError(__LINE__, initialize);
}
// 在第二个语句中,RoInitializeWrapper::HRESULT 运算符从
// Windows::Foundation::Initialize 调用返回 HRESULT。3. 为 ABI::Windows::Foundation::IUriRuntimeClassFactory 接口创建激活工厂。// Get the activation factory for the IUriRuntimeClass interface.
ComPtr<IUriRuntimeClassFactory> uriFactory;
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
if (FAILED(hr))
{return PrintError(__LINE__, hr);
}
// Windows 运行时使用完全限定名来标识类型。
// RuntimeClass_Windows_Foundation_Uri 参数是 Windows 运行时提供的字符串,
// 其中包含所需的运行时类名称。// 4. 初始化 Microsoft::WRL::Wrappers::HString 变量,
// 其用于表示 URI "https://www.microsoft.com"。// Create a string that represents a URI.
HString uriHString;
hr = uriHString.Set(L"http://www.microsoft.com");
if (FAILED(hr))
{return PrintError(__LINE__, hr);
}
// 在 Windows 运行时中,不要为 Windows 运行时将使用的字符串分配内存。
// 相反,Windows 运行时会在它维护和用于操作的缓冲区中创建字符串的副本,
// 然后将句柄返回到其创建的缓冲区。// 4. 使用 IUriRuntimeClassFactory::CreateUri 工厂方法创建
// ABI::Windows::Foundation::IUriRuntimeClass 对象。// Create the IUriRuntimeClass object.
ComPtr<IUriRuntimeClass> uri;
hr = uriFactory->CreateUri(uriHString.Get(), &uri);
if (FAILED(hr))
{return PrintError(__LINE__, hr);
}// 5. 调用 IUriRuntimeClass::get_Domain 方法以检索 Domain 属性的值。// Get the domain part of the URI.
HString domainName;
hr = uri->get_Domain(domainName.GetAddressOf());
if (FAILED(hr))
{return PrintError(__LINE__, hr);
}// 6. 将域名输出到控制台并返回。 所有 ComPtr 和 RAII 对象都离开范围并自动释放。// Print the domain name and return.
wprintf_s(L"Domain name: %s\n", domainName.GetRawBuffer(nullptr));// All smart pointers and RAII objects go out of scope here.
WindowsGetStringRawBuffer 函数可检索 URI 字符串的基础 Unicode 格式。