Преобразование объекта winrt :: UI :: Xaml :: Controls :: TextBlock в объект C ++ / CX - PullRequest
0 голосов
/ 07 августа 2020

Я портирую свой проект с C ++ / CX на C ++ / WinRT. Для этого мне нужно сделать что-то вроде этого: https://docs.microsoft.com/en-us/windows/uwp/cpp-and-winrt-apis/interop-winrt-cx.

Microsoft рекомендует использовать такие вспомогательные функции для взаимодействия.

from_cx и to_cx функции Вспомогательная функция ниже преобразует объект C ++ / CX в эквивалентный объект C ++ / WinRT. Функция приводит объект C ++ / CX к его базовому указателю интерфейса IUnknown. Затем он вызывает QueryInterface для этого указателя, чтобы запросить интерфейс по умолчанию для объекта C ++ / WinRT. QueryInterface - это Windows двоичный интерфейс приложения среды выполнения (ABI), эквивалентный расширению safe_cast C ++ / CX. И функция winrt :: put_abi извлекает адрес базового указателя интерфейса IUnknown объекта C ++ / WinRT, чтобы его можно было установить на другое значение.

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

Вспомогательная функция ниже преобразует объект C ++ / WinRT в эквивалентный объект C ++ / CX. Функция winrt :: get_abi извлекает указатель на базовый интерфейс IUnknown объекта C ++ / WinRT. Функция преобразует этот указатель на объект 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. Что мне не хватает?

1 Ответ

1 голос
/ 07 августа 2020

Преобразование объекта winrt :: UI :: Xaml :: Controls :: TextBlock в объект C ++ / CX

Если вы хотите порт a C ++ / WinRT объект в C ++ / CX объект. Вы можете создать проект Windows Runtime Component ( C ++ / WinRT ) для решения и поместить в него код преобразования. Затем сделайте так, чтобы проект C ++ / WinRT ссылался на указанный выше компонент (щелкните правой кнопкой мыши имя проекта C ++ / WinRT в обозревателе решений, нажмите «Добавить», выберите «Ссылки», выберите только что добавленное имя компонента. в разделе "Проекты" в диалоговом окне "Добавить ссылку").

Примечание

Вам необходимо использовать Потребление Windows Расширение времени выполнения> Да (/ ZM) в проекте Windows Runtime Component (C ++ / WinRT) вместо проекта C ++ / WinRT.

Затем в Windows Runtime Component ( 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. Вы можете смешивать C ++ / CX и C ++ / WinRT вне типов страниц XAML в одном проекте.

Функция, которая использует код преобразования в классе проекта компонента, должна быть объявлена ​​в классе idl сначала файл, иначе мы не сможем ссылаться на функцию в другом проекте.

Обновление:

Вот простой образец , который я создал, когда нажал кнопку в основном проекте, я вызвал метод Windows Runtime Component, чтобы запустить метод to_cx, вы можете это проверить.

...