Question

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);
    }
}
Was it helpful?

Solution

There are two sets of namespaces:

  • those rooted in the global namespace (e.g. Windows::Foundation)
  • those rooted in the 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
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top