When I create a winrt component using WRL, the problem is that I can only use ABI::Windows::xxx
namespace, and I cannot use Windows::UI::Xaml::Media::Imaging
namespace in WRL.
Then, how to create a build-in winrt component as a return value?
// 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);
}
}
There are two sets of namespaces:
Windows::Foundation
)ABI
namespace (e.g. ABI::Windows::Foundation
)The contents of each are "the same." For example, Windows::Foundation::IUriRuntimeClass
names the same interface as ABI::Windows::Foundation::IUriRuntimeClass
.
So, why are there two sets of namespaces? the namespaces rooted in the global namespace are reserved for use by C++/CX: it generates its projections of runtime classes in those namespaces. When you're using WRL, you'll always work with the namespaces rooted in the ABI
namespace (which are the "unprojected" names, that is, they're exactly what exist at the ABI layer).
Runtime classes are instantiated ("activated") in one of two ways. If the type is default constructible, it may be default constructed by calling RoActivateInstance
. If a type declares other constructors, those constructors may be called by getting the activation factory for the runtime type by calling RoGetActivationFactory
. As an example, you can default construct a BitmapImage
like so:
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 also has a useful function template, Windows::Foundation::ActivateInstance
, that both calls RoActivateInstance
and performs the QueryInterface
to the desired target interface:
using namespace Windows::Foundation;
ComPtr<IBitmapImage> bitmapImage;
if (FAILED(ActivateInstance(classId.Get(), bitmapImage.GetAddressOf())))
{
// Handle failure
}