Как вернуть встроенный компонент WinRT с помощью WRL?

Когда я создаю компонент WinRT с использованием WRL, проблема заключается в том, что я могу использовать только ABI::Windows::xxx пространство имен, и я не могу использовать Windows::UI::Xaml::Media::Imaging пространство имен в WRL.

Затем, как создать встроенный компонент WinRT в качестве возвращаемого значения?

// idl
import "inspectable.idl";
import "Windows.Foundation.idl";
import "Windows.UI.Xaml.Media.Imaging.idl";

namespace Decoder
{
interface IPhotoDecoder;
runtimeclass PhotoDecoder;

interface IPhotoDecoder : IInspectable
{
HRESULT Decode([in] int width, [in] int height, [out, retval] Windows.UI.Xaml.Media.Imaging.BitmapImage **ppBitmapImage);
}

[version(COMPONENT_VERSION), activatable(COMPONENT_VERSION)]
runtimeclass PhotoDecoder
{
[default] interface IPhotoDecoder;
}
}

// cpp
using namespace Microsoft::WRL;
using namespace Windows::Foundation;
using namespace ABI::Windows::UI::Xaml::Media::Imaging;
namespace ABI
{
namespace Decoder
{
class PhotoDecoder: public RuntimeClass<IPhotoDecoder>
{
InspectableClass(L"Decoder.PhotoDecoder", BaseTrust)

public:
PhotoDecoder()
{
}

HRESULT __stdcall Decode(_In_ int width, _In_ int height, _Out_ IBitmapImage **ppBitmapImage)
{
// How to create Windows.UI.Xaml.Media.Imaging.BitmapImage without using Windows::UI::Xaml::Media::Imaging
}

};

ActivatableClass(PhotoDecoder);
}
}

1

Решение

Существует два набора пространств имен:

  • укорененные в глобальном пространстве имен (например, Windows::Foundation)
  • те, кто укоренен в ABI пространство имен (например, ABI::Windows::Foundation)

Содержимое каждого «одинаковое». Например, Windows::Foundation::IUriRuntimeClass называет тот же интерфейс, что и ABI::Windows::Foundation::IUriRuntimeClass,

Итак, почему есть два набора пространств имен? пространства имен, укорененные в глобальном пространстве имен, зарезервированы для использования C ++ / CX: он генерирует свои проекции классов времени выполнения в этих пространствах имен. Когда вы используете WRL, вы всегда будете работать с пространствами имен, укорененными в ABI Пространство имен (это «непроектированные» имена, то есть именно то, что существует на уровне ABI).

Классы времени выполнения создаются («активируются») одним из двух способов. Если тип является конструируемым по умолчанию, он может быть создан по умолчанию путем вызова RoActivateInstance. Если тип объявляет другие конструкторы, эти конструкторы могут быть вызваны путем получения фабрики активации для типа времени выполнения путем вызова RoGetActivationFactory. Например, вы можете по умолчанию построить BitmapImage вот так:

using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

using namespace ABI::Windows::UI::Xaml::Media::Imaging;

HStringReference classId(RuntimeClass_Windows_UI_Xaml_Media_Imaging_BitmapImage);

ComPtr<IInspectable> inspectable;
if (FAILED(RoActivateInstance(classId.Get(), inspectable.GetAddressOf())))
{
// Handle failure
}

ComPtr<IBitmapImage> bitmapImage;
if (FAILED(inspectable.As(&bitmapImage)))
{
// Handle failure
}

WRL также имеет полезный шаблон функции, Windows::Foundation::ActivateInstance, что оба звонка RoActivateInstance и выполняет QueryInterface к желаемому целевому интерфейсу:

using namespace Windows::Foundation;

ComPtr<IBitmapImage> bitmapImage;
if (FAILED(ActivateInstance(classId.Get(), bitmapImage.GetAddressOf())))
{
// Handle failure
}
6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]