WRL を使用して組み込みの winrt コンポーネントを返すにはどうすればよいですか?
-
12-12-2019 - |
質問
WRL を使用して winrt コンポーネントを作成する場合、問題は、 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);
}
}
解決
名前空間には 2 つのセットがあります。
- グローバル名前空間に根ざしたもの (例:
Windows::Foundation
) - に根ざしたもの
ABI
名前空間 (例:ABI::Windows::Foundation
)
それぞれの内容は「同じ」です。例えば、 Windows::Foundation::IUriRuntimeClass
と同じインターフェースに名前を付けます ABI::Windows::Foundation::IUriRuntimeClass
.
では、なぜ 2 セットの名前空間があるのでしょうか?グローバル名前空間をルートとする名前空間は、C++/CX で使用するために予約されています。これらの名前空間でランタイム クラスのプロジェクションを生成します。WRL を使用するときは、常に、 ABI
名前空間 (「投影されていない」名前、つまり、まさに ABI レイヤーに存在するものです)。
ランタイム クラスは、2 つの方法のいずれかでインスタンス化 (「アクティブ化」) されます。型がデフォルトで構築可能な場合、呼び出しによってデフォルトで構築される可能性があります。 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
}