Együttműködés a Direct2D-vel

A Win2D a Direct2D tetején rétegként van implementálva, és mindkét irányban támogatja az interopálást. Ha Win2D-objektummal rendelkezik, hozzáférhet a implementálásához használt natív Direct2D-objektumhoz. Ha Direct2D-objektummal rendelkezik, megkeresheti a burkoló Win2D objektumot, vagy létrehozhat egy új burkolót, ha még nem létezik.

Az interoperabilitás lehetővé teszi, hogy a Win2D-t natív DirectX API-kkal együtt használja. Írhat olyan alkalmazást, amely többnyire Win2D-t használ, de bármikor leugra a natív DirectX-hez – esetleg meghívhat egy másik API-t vagy külső összetevőt, amely natív felületeket igényel. Vagy az alkalmazás lehet többnyire natív DirectX, de átválthat a Win2D-re bizonyos helyeken, ahol extra kényelemre vagy C#-támogatásra van szüksége.

Interop API-k

A C++/CX interop API-k a Microsoft.Graphics.Canvas.native.h fejlécfájlban vannak definiálva:

#include <Microsoft.Graphics.Canvas.native.h>

using namespace Microsoft::Graphics::Canvas;

A Win2D-objektum által burkolt natív Direct2D-objektum lekérése:

template<typename T, typename U>
Microsoft::WRL::ComPtr<T> GetWrappedResource(U^ wrapper);

template<typename T, typename U>
Microsoft::WRL::ComPtr<T> GetWrappedResource(CanvasDevice^ device, U^ wrapper);

template<typename T, typename U>
Microsoft::WRL::ComPtr<T> GetWrappedResource(CanvasDevice^ device, U^ wrapper, float dpi);

A legtöbb típushoz GetWrappedResource csak Win2D burkolóobjektumot lehet meghívni paraméterként. Néhány típus esetében (lásd az alábbi táblázatot) azt is át kell adni egy eszköznek és/vagy DPI-értéknek. Nem hiba eszközt vagy DPI-t megadni a(z) GetWrappedResource használatakor olyan típusokkal, amelyek nem igénylik ezeket.

Natív Direct2D-objektumot burkoló Win2D-objektum beszerzéséhez:

template<typename WRAPPER>
WRAPPER^ GetOrCreate(IUnknown* resource);

template<typename WRAPPER>
WRAPPER^ GetOrCreate(CanvasDevice^ device, IUnknown* resource);

template<typename WRAPPER>
WRAPPER^ GetOrCreate(ID2D1Device1* device, IUnknown* resource);

template<typename WRAPPER>
WRAPPER^ GetOrCreate(CanvasDevice^ device, IUnknown* resource, float dpi);

template<typename WRAPPER>
WRAPPER^ GetOrCreate(ID2D1Device1* device, IUnknown* resource, float dpi);

GetOrCreate visszaad egy meglévő wrapperpéldányt, ha már létezik, vagy létrehoz egy újat, ha még nem létezik. Ha ugyanazon a natív objektumon ismételten hívja meg, minden alkalommal ugyanazt a burkolóobjektumot adja vissza, amíg az a burkolóobjektum-példány létezik. Ha a burkolóobjektumra mutató összes hivatkozás felszabadul, úgy hogy a referenciaszáma nullára csökken, és az objektum megsemmisül, akkor a(z) GetOrCreate bármely későbbi meghívásakor új burkolóobjektumot kell létrehozni.

Egyes típusok esetében a GetOrCreate meghívható úgy, hogy paraméterként csak egy Direct2D-erőforrásobjektumot ad meg, míg más típusoknál (lásd az alábbi táblázatot) az eszközt és a DPI-értéket is meg kell adni. Nem hiba eszközt vagy DPI-t megadni a(z) GetOrCreate használatakor olyan típusokkal, amelyek nem igénylik ezeket. Ha már létezik Win2D-burkolóobjektum, akkor az eszköz és a DPI még olyan típusok esetében is elhagyható, amelyekhez egyébként szükség lenne rájuk: ezeket a paramétereket csak új burkolóobjektum-példányok létrehozásakor használják.

GetOrCreate megérti az öröklési hierarchiákat, és mindig a megfelelő, leginkább származtatott burkolótípust hozza létre. Ha például a(z) GetOrCreate<CanvasBitmap>(ID2D1Bitmap1*) jelzővel rendelkező ID2D1Bitmap1 paraméterrel hívja meg a(z) D2D1_BITMAP_OPTIONS_TARGET elemet, akkor a visszaadott burkoló példány valójában egy CanvasRenderTarget lesz (amely a(z) CanvasBitmap leszármazottja). Fordítva, ha a GetOrCreate<CanvasRenderTarget>(ID2D1Bitmap1*) hívásakor olyan ID2D1Bitmap1-et ad át, amely nem rendelkezik D2D1_BITMAP_OPTIONS_TARGET-vel, a rendszer érvénytelen típuskonverziós kivételt dob.

Ha ezt a végletekig visszük, akkor érvényes meghívni a GetOrCreate<Object>(IUnknown*) és a GetWrappedResource<IUnknown>(Object^) elemet is.

Az interop-t támogató típusok

Win2D-típus Direct2D-típus GetOrCreate Paraméterek GetWrappedResource Paraméterek
CanvasBitmap ID2D1Bitmap1 Nélkül D2D1_BITMAP_OPTIONS_TARGET Device -
CanvasCachedGeometry ID2D1GeometryRealization Device -
CanvasCommandList ID2D1CommandList Device -
CanvasDevice ID2D1Device1 - -
CanvasDrawingSession ID2D1DeviceContext1 - -
CanvasFontFace IDWriteFontFaceReference - -
CanvasFontSet IDWriteFontSet - -
CanvasGeometry ID2D1Geometry, vagy annak egyik származtatott felülete ID2D1PathGeometry, ID2D1RectangleGeometry, ID2D1RoundedRectangleGeometry, ID2D1EllipseGeometry, ID2D1TransformedGeometry vagy ID2D1GeometryGroup Device -
CanvasGradientMesh ID2D1GradientMesh Device -
CanvasImageBrush ID2D1BitmapBrush1 (ha a kép egy CanvasBitmap, és a(z) SourceRectanglenull) vagy ID2D1ImageBrush (ha ez bármilyen más típusú ICanvasImage, vagy ha SourceRectangle is set) Device Opcionális DPI^1
CanvasLinearGradientBrush ID2D1LinearGradientBrush Device -
CanvasNumberSubstitution IDWriteNumberSubstitution - -
CanvasRadialGradientBrush ID2D1RadialGradientBrush Device -
CanvasRenderTarget ID2D1Bitmap1 és D2D1_BITMAP_OPTIONS_TARGET Device -
CanvasSolidColorBrush ID2D1SolidColorBrush Device -
CanvasStrokeStyle ID2D1StrokeStyle1 - Device
CanvasSvgDocument ID2D1SvgDocument^2 Device -
CanvasSwapChain IDXGISwapChain1 Eszköz, DPI -
CanvasTextFormat IDWriteTextFormat1 - -
CanvasTextLayout IDWriteTextLayout3 Device -
CanvasTextRenderingParameters IDWriteRenderingParams3 - -
CanvasTypography IDWriteTypography - -
CanvasVirtualBitmap ID2D1ImageSource vagy ID2D1TransformedImageSource Device -
ColorManagementProfile ID2D1ColorContext Device Device
EffectTransferTable3D ID2D1LookupTable3D Device -
Microsoft.Graphics.Canvas.Effects.* (több Win2D-osztály megfeleltetése ugyanarra a D2D-típusra) ID2D1Effect a megfelelő D2D1_PROPERTY_TYPE_CLSID Device Eszköz, opcionális DPI^1

Note

^1: az opcionális DPI azt jelenti, hogy a DPI-érték megadása nélkül is érvényes erre a típusra meghívni GetWrappedResource , de ha a DPI-t adja meg, a Win2D hatékonyabban konfigurálhatja az effektusdiagramokat a redundáns DPI-kompenzációs csomópontok kihagyásával. Ez akkor alkalmazandó, amikor egy effektuson a(z) GetWrappedResource hívást végzi, vagy egy olyan CanvasImageBrush esetén, amelynek forrásképe egy effektus.

Note

^2: ha egy CanvasSvgDocument natív C++ interop használatával egy ID2D1SvgDocument-ből jön létre, a rendszer figyelmen kívül hagyja a ID2D1SvgDocument nézetablakának méretét.

Együttműködés a C++/CX használatával

Íme egy példa arra, hogy a Win2D hogyan tud együttműködni a Direct2D-vel a C++ használatával:

#include <Microsoft.Graphics.Canvas.native.h>
#include <d2d1_2.h>

using namespace Microsoft::Graphics::Canvas;
using namespace Microsoft::WRL;

// Interop Win2D -> Direct2D.
CanvasDevice^ canvasDevice = ...;
CanvasBitmap^ canvasBitmap = ...;

ComPtr<ID2D1Device> nativeDevice = GetWrappedResource<ID2D1Device>(canvasDevice);
ComPtr<ID2D1Bitmap1> nativeBitmap = GetWrappedResource<ID2D1Bitmap1>(canvasBitmap);

// Interop Direct2D -> Win2D.
canvasDevice = GetOrCreate<CanvasDevice>(nativeDevice.Get());
bitmap = GetOrCreate<CanvasBitmap>(canvasDevice, nativeBitmap.Get());

Note

Az interop is lehetséges C#-on keresztül, különböző eszközökkel (például beépített COM/WinRT interop használatával, a CsWinRT API-ján keresztül, vagy titkos kötések használatával). A C#-ban történő manuális interopról további információt a CsWinRT dokumentációjában talál.

Együttműködés a C++/WinRT használatával

A C++/WinRT használatával is elvégezheti az interopálást a fentiek módosításával. Vegye figyelembe, hogy a Win2D Windows-futtatókörnyezet-összetevők C++/WinRT fejléceit automatikusan létre kell hozni, amikor hozzáadja a Win2D NuGet-csomagot a C++/WinRT-projekthez. Az interop esetében azonban továbbra is használnia kell a fejlécfájlt Microsoft. Graphics.Canvas.native.h, amely tartalmazza az alacsony szintű ABI felületet ICanvasFactoryNative a névtérbenABI::Microsoft::Graphics::Canvas. Az interfész a következő függvényekkel rendelkezik, amelyekkel interopálást hajthat végre.

HRESULT GetOrCreate(ICanvasDevice* device, IUnknown* resource, float dpi, IInspectable** wrapper);
HRESULT GetNativeResource(ICanvasDevice* device, float dpi, REFIID iid, void** resource);

Íme egy példa, amely bemutatja, hogyan hozhat létre egy CanvasVirtualBitmap elemet egy IWICBitmapSource elemből a IWICBitmapSource és a megosztott CanvasDevice használatával.

#include "pch.h"
#include <wincodec.h>
#include <wincodecsdk.h>
#include <winrt/Microsoft.Graphics.Canvas.h> //This defines the C++/WinRT interfaces for the Win2D Windows Runtime Components
#include <Microsoft.Graphics.Canvas.h> //This defines the low-level ABI interfaces for the Win2D Windows Runtime Components
#include <Microsoft.Graphics.Canvas.native.h> //This is for interop
#include <d2d1_3.h>

using namespace winrt::Microsoft::Graphics::Canvas;
namespace abi {
  using namespace ABI::Microsoft::Graphics::Canvas;
}

namespace winrt::Win2DInteropTest::implementation {
  CanvasVirtualBitmap CreateVirtualBitmapFromBitmapSource(com_ptr<IWICBitmapSource> const& pBitmapSource){
    CanvasDevice sharedDevice = CanvasDevice::GetSharedDevice();

    //First we need to get an ID2D1Device1 pointer from the shared CanvasDevice
    com_ptr<abi::ICanvasResourceWrapperNative> nativeDeviceWrapper = sharedDevice.as<abi::ICanvasResourceWrapperNative>();
    com_ptr<ID2D1Device1> pDevice{ nullptr };
    check_hresult(nativeDeviceWrapper->GetNativeResource(nullptr, 0.0f, guid_of<ID2D1Device1>(), pDevice.put_void()));

    //Next we need to call some Direct2D functions to create the ID2D1ImageSourceFromWic object
    com_ptr<ID2D1DeviceContext1> pContext{ nullptr };
    check_hresult(pDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, pContext.put()));
    com_ptr<ID2D1DeviceContext2> pContext2 = pContext.as<ID2D1DeviceContext2>();
    com_ptr<ID2D1ImageSourceFromWic> pImage{ nullptr };
    check_hresult(pContext2->CreateImageSourceFromWic(pBitmapSource.get(), D2D1_IMAGE_SOURCE_LOADING_OPTIONS_RELEASE_SOURCE, pImage.put()));

    //Finally we need to wrap the ID2D1ImageSourceFromWic object inside 
    com_ptr<::IInspectable> pInspectable{ nullptr };
    auto factory = winrt::get_activation_factory<CanvasDevice, abi::ICanvasFactoryNative>(); //abi::ICanvasFactoryNative is the activation factory for the CanvasDevice class
    check_hresult(factory->GetOrCreate(sharedDevice.as<abi::ICanvasDevice>().get(), pImage.as<::IUnknown>().get(), 0.0f, pInspectable.put())); //Note abi::ICanvasDevice is defined in the header Microsoft.Graphics.Canvas.h
    CanvasVirtualBitmap cvb = pInspectable.as<CanvasVirtualBitmap>();
    return cvb;
  }
}

Ne felejtse el felvenni a fejlécet <unknwn.h> a pch.h fájlba a WinRT-fejlécek előtt (az SDK 17763-ban és újabb verzióiban szükséges).