将winrt::UI::Xaml::Controls::TextBlock对象转换为C++/CX对象



我正在将我的项目从C++/CX移植到C++/WinRT。为此,我需要做一些互操作操作,如下所示:https://learn.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/interop-winrt-cx.

为了实现互操作性,Microsoft建议使用类似的辅助功能。

from_cx和to_cx函数下面的helper函数将C++/CX对象转换为等效的C++/WinRT对象。该函数将一个C++/CX对象强制转换为其基础IUnknown接口指针。然后,它在该指针上调用QueryInterface,以查询C++/WinRT对象的默认接口。QueryInterface是Windows运行时应用程序二进制接口(ABI(,相当于C++/CX safe_cast扩展。并且,winrt::put_abi函数检索C++/winrt对象的底层IUnknown接口指针的地址,以便将其设置为另一个值。

template <typename T>
T from_cx(Platform::Object^ from)
{
T to{ nullptr };
winrt::check_hresult(reinterpret_cast<::IUnknown*>(from)
->QueryInterface(winrt::guid_of<T>(),
reinterpret_cast<void**>(winrt::put_abi(to))));
return to;
}

下面的helper函数将C++/WinRT对象转换为等效对象C++/CX对象。winrt::get_abi函数检索指向C++/WinRT对象的底层IUnknown接口。函数强制转换在使用C++/CX safe_cast之前指向C++/CX对象的指针扩展以查询所请求的C++/CX类型。

template <typename T>
T^ to_cx(winrt::Windows::Foundation::IUnknown const& from)
{
return safe_cast<T^>(reinterpret_cast<Platform::Object^>(winrt::get_abi(from)));
}

但是,当我做这样的事情时:

auto text = winrt::Windows::UI::Xaml::Controls::TextBlock();
Windows::UI::Xaml::FrameworkElement^ cx = to_cx<Windows::UI::Xaml::FrameworkElement^>(text);

我得到一个错误:

没有函数模板的实例"to_cx";匹配参数列表

参数类型为:(winrt::Windows::UI::Xanl::Controls::TextBlock(

但我确实看到TextBlock继承了IUnknown。我错过了什么?

将winrt::UI::Xaml::Controls::TextBlock对象转换为C++/CX对象

如果要将C++/WinRT对象移植到C++/CX。您可以为该解决方案创建Windows运行时组件(C++/WinRT(项目,并将转换代码放入其中。然后使C++/WinRT++/WinRT项目名称,单击"添加",选择"引用",在"添加引用"对话框中的"项目"下选择刚才添加的组件名称(。

注意

您需要使用Consume Windows Runtime Extension>是(/ZM(在Windows运行时组件(C++/WinRT(项目中,而不是在C++/WinRT项目中。

然后,在Windows运行时组件(C++/WinRT(中,添加cx命名空间和WinRT命名空间,以使用不同的语言来区分不同的对象。

以下代码可以放入组件项目的类中。

添加所需的标头,例如:

#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.h>
In the cx namespace, add  using statements:
namespace cx
{
using namespace Windows::Foundation;
using namespace Windows::UI::Xaml;
}
// And, in the winrt namespace, add the needed using statements:
namespace winrt
{
using namespace Windows;
using namespace Windows::ApplicationModel::Core;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Numerics;
using namespace Windows::UI;
using namespace Windows::UI::Core;
using namespace Windows::UI::Composition;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml;
}
Add the to_cx method:
template <typename T>
T^ to_cx(winrt::Windows::Foundation::IUnknown const& from)
{
return safe_cast<T^>(reinterpret_cast<Platform::Object^>(winrt::get_abi(from)));
}
//Change the code:
/*auto text = winrt::Windows::UI::Xaml::Controls::TextBlock();
Windows::UI::Xaml::FrameworkElement^ cx = to_cx<Windows::UI::Xaml::FrameworkElement^>(text);*/
auto text = winrt::Windows::UI::Xaml::Controls::TextBlock();
cx::FrameworkElement^ cx = to_cx<cx::FrameworkElement>(text);

请注意:

请不要将转换代码放入XAML页面,因为您的XAML页面类型需要完全是以太C++/CX或完全是C++/WinRT。您可以在同一项目中混合使用XAML页面类型之外的C++/CX和C++/WinRT。

在组件项目的类中使用转换代码的函数必须首先在类的idl文件中声明,否则我们不能在另一个项目中引用该函数。

更新:

这里是我创建的一个简单的示例,当点击主项目中的按钮时,我调用了Windows Runtime Component的方法来触发to_cx方法,你可以检查它

最新更新