How to return a build-in winrt component using WRL?

北慕城南 提交于 2019-12-10 11:29:30

问题


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

回答1:


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
}


来源:https://stackoverflow.com/questions/12687502/how-to-return-a-build-in-winrt-component-using-wrl

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!