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

Converting a winrt::UI::Xaml::Controls::TextBlock object to C++/CX object

我正在将我的项目从 C++/CX 移植到 C++/WinRT。为此,我需要像这样进行一些互操作:https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/interop-winrt-cx.

Microsoft 建议使用此类辅助函数来实现互操作性。

from_cx and to_cx functions The helper function below converts a C++/CX object to an equivalent C++/WinRT object. The function casts a C++/CX object to its underlying IUnknown interface pointer. It then calls QueryInterface on that pointer to query for the default interface of the C++/WinRT object. QueryInterface is the Windows Runtime application binary interface (ABI) equivalent of the C++/CX safe_cast extension. And, the winrt::put_abi function retrieves the address of a C++/WinRT object's underlying IUnknown interface pointer so that it can be set to another value.

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;
}

The helper function below converts a C++/WinRT object to an equivalent C++/CX object. The winrt::get_abi function retrieves a pointer to a C++/WinRT object's underlying IUnknown interface. The function casts that pointer to a C++/CX object before using the C++/CX safe_cast extension to query for the requested C++/CX type.

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);

我收到一个错误:

No instance of function template "to_cx" matches the argument list

Argument types are: (winrt::Windows::UI:: Xanl::Controls::TextBlock)

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

Converting a winrt::UI::Xaml::Controls::TextBlock object to C++/CX object

如果你想port一个C++/WinRTobject到一个C++/CXobject。您可以为解决方案创建 Windows Runtime Component(C++/WinRT) 项目并将转换代码放入其中。然后使 C++/WinRT 项目引用 在组件上方(在解决方案资源管理器中右键单击 C++/WinRT 项目名称,单击“添加”,选择“引用”,select 您刚刚在“添加引用”对话框中的“项目”下添加的组件名称).

备注

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

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

下面的代码可以放到你的组件项目的class.

添加需要的headers如:

#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。

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

更新:

这里是我创建的一个简单的sample,当点击主工程中的按钮时,我调用了Windows运行时组件的方法来触发to_cx方法,你可以检查一下。