Frage

Wenn ich eine WinRT-Komponente mit WRL erstelle, besteht das Problem darin, dass ich sie nur verwenden kann ABI::Windows::xxx Namespace, und ich kann ihn nicht verwenden Windows::UI::Xaml::Media::Imaging Namensraum in WRL.

Wie erstelle ich dann eine integrierte WinRT-Komponente als Rückgabewert?

// 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);
    }
}
War es hilfreich?

Lösung

Es gibt zwei Gruppen von Namespaces:

  • diejenigen, die im globalen Namensraum verwurzelt sind (z. B. Windows::Foundation)
  • diejenigen, die in der verwurzelt sind ABI Namensraum (z.B. ABI::Windows::Foundation)

Der Inhalt eines jeden ist "dasselbe". Zum Beispiel, Windows::Foundation::IUriRuntimeClass benennt die gleiche Schnittstelle wie ABI::Windows::Foundation::IUriRuntimeClass.

Warum gibt es also zwei Gruppen von Namespaces?Die im globalen Namespace verwurzelten Namespaces sind für die Verwendung durch C++/CX reserviert:Es generiert seine Projektionen von Laufzeitklassen in diesen Namespaces.Wenn Sie WRL verwenden, arbeiten Sie immer mit den Namespaces, die in der verwurzelt sind ABI Namespace (das sind die „nicht projizierten“ Namen, das heißt, sie sind genau das, was auf der ABI-Ebene existiert).

Laufzeitklassen werden auf zwei Arten instanziiert („aktiviert“).Wenn der Typ standardmäßig konstruierbar ist, kann er standardmäßig durch einen Aufruf erstellt werden RoActivateInstance.Wenn ein Typ andere Konstruktoren deklariert, können diese Konstruktoren aufgerufen werden, indem durch Aufrufen die Aktivierungsfactory für den Laufzeittyp abgerufen wird RoGetActivationFactory.Als Beispiel können Sie standardmäßig a konstruieren BitmapImage etwa 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 verfügt auch über eine nützliche Funktionsvorlage, Windows::Foundation::ActivateInstance, dass beide Anrufe RoActivateInstance und führt die QueryInterface zur gewünschten Zielschnittstelle:

using namespace Windows::Foundation;

ComPtr<IBitmapImage> bitmapImage;
if (FAILED(ActivateInstance(classId.Get(), bitmapImage.GetAddressOf())))
{
    // Handle failure
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top