Question

Lorsque je crée un composant winrt à l'aide de WRL, le problème est que je ne peux utiliser que ABI::Windows::xxx espace de noms, et je ne peux pas utiliser Windows::UI::Xaml::Media::Imaging espace de noms dans WRL.

Alors, comment créer un composant winrt intégré comme valeur de retour ?

// 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);
    }
}
Était-ce utile?

La solution

Il existe deux ensembles d'espaces de noms :

  • ceux enracinés dans l'espace de noms global (par ex. Windows::Foundation)
  • ceux enracinés dans le ABI espace de noms (par ex. ABI::Windows::Foundation)

Le contenu de chacun est «le même». Par exemple, Windows::Foundation::IUriRuntimeClass nomme la même interface que ABI::Windows::Foundation::IUriRuntimeClass.

Alors, pourquoi y a-t-il deux ensembles d’espaces de noms ?les espaces de noms ancrés dans l'espace de noms global sont réservés à une utilisation par C++/CX :il génère ses projections de classes d'exécution dans ces espaces de noms.Lorsque vous utilisez WRL, vous travaillerez toujours avec les espaces de noms enracinés dans le ABI espace de noms (qui sont les noms "non projetés", c'est-à-dire qu'ils sont exactement ceux qui existent au niveau de la couche ABI).

Les classes d'exécution sont instanciées (« activées ») de deux manières.Si le type est constructible par défaut, il peut être construit par défaut en appelant RoActivateInstance.Si un type déclare d'autres constructeurs, ces constructeurs peuvent être appelés en obtenant la fabrique d'activation pour le type d'exécution en appelant RoGetActivationFactory.À titre d'exemple, vous pouvez construire par défaut un BitmapImage ainsi:

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 dispose également d'un modèle de fonction utile, Windows::Foundation::ActivateInstance, que les deux appellent RoActivateInstance et effectue le QueryInterface à l'interface cible souhaitée :

using namespace Windows::Foundation;

ComPtr<IBitmapImage> bitmapImage;
if (FAILED(ActivateInstance(classId.Get(), bitmapImage.GetAddressOf())))
{
    // Handle failure
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top