Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Win2D implementeras som ett lager ovanpå Direct2D och stöder interop i båda riktningarna. Om du har ett Win2D-objekt kan du komma åt det interna Direct2D-objektet som används för att implementera det. Om du har ett Direct2D-objekt kan du leta upp Win2D-objektet som omsluter det eller skapa en ny omslutning om det inte redan finns något.
Med Interop kan du blanda och matcha Win2D med interna DirectX-API:er. Du kan skriva en app som till största delen använder Win2D, men växla över till DirectX på låg nivå när som helst – kanske för att anropa något annat API eller en tredjepartskomponent som kräver nativa gränssnitt. Eller så kan din app till största delen vara inbyggd DirectX, men du kan växla över till Win2D på specifika platser där du vill ha dess extra bekvämlighet eller C#-support.
Interop-API:er
C++/CX interop-API:er definieras i rubriken Microsoft. Graphics.Canvas.native.h:
#include <Microsoft.Graphics.Canvas.native.h>
using namespace Microsoft::Graphics::Canvas;
Så här hämtar du det inbyggda Direct2D-objektet som omsluts av ett Win2D-objekt:
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);
För de flesta typer GetWrappedResource kan anropas med endast ett Win2D-omslutningsobjekt som parameter. För några typer (se tabellen nedan) måste den också skickas till en enhet och/eller ett DPI-värde. Det är inte ett fel att skicka en enhet eller DPI när du använder GetWrappedResource med typer som inte kräver dem.
Så här hämtar du ett Win2D-objekt som omsluter ett internt Direct2D-objekt:
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 returnerar en befintlig omslutningsinstans om en redan finns eller skapar en ny omslutning om den inte finns. Om det anropas upprepade gånger på samma nativa objekt returneras samma wrapper varje gång, så länge wrapperinstansen fortfarande existerar. Om alla referenser till wrappern släpps så att dess referensantal går till noll och den destrueras, måste varje senare anrop till GetOrCreate skapa en ny wrapper.
För vissa typer GetOrCreate kan anropas med endast ett Direct2D-resursobjekt som parameter, medan det för andra typer (se tabellen nedan) också måste skickas en enhet och ett DPI-värde. Det är inte ett fel att skicka en enhet eller DPI när du använder GetOrCreate med typer som inte kräver dem. Om det redan finns en Win2D-omslutning är det ok att utelämna enheten och DPI även för typer som normalt skulle behöva dem: dessa parametrar används endast när nya omslutningsinstanser skapas.
GetOrCreate förstår arvshierarkier och skapar alltid lämplig mest härledd omslutningstyp. Om du till exempel anropar GetOrCreate<CanvasBitmap>(ID2D1Bitmap1*) med en ID2D1Bitmap1 som har D2D1_BITMAP_OPTIONS_TARGET flaggan blir den returnerade wrapper-instansen i själva verket en CanvasRenderTarget (som härleds från CanvasBitmap). Tvärtom, om du anropar GetOrCreate<CanvasRenderTarget>(ID2D1Bitmap1*) med en ID2D1Bitmap1 som inte har D2D1_BITMAP_OPTIONS_TARGET, kommer detta att utlösa ett ogiltigt cast-undantag.
Om du tar detta till det yttersta är det giltigt att anropa GetOrCreate<Object>(IUnknown*), och även GetWrappedResource<IUnknown>(Object^).
Typer som stöder interop
| Win2D-typ | Direct2D-typ |
GetOrCreate Parametrar |
GetWrappedResource Parametrar |
|---|---|---|---|
CanvasBitmap |
ID2D1Bitmap1 utan D2D1_BITMAP_OPTIONS_TARGET |
Device | - |
CanvasCachedGeometry |
ID2D1GeometryRealization |
Device | - |
CanvasCommandList |
ID2D1CommandList |
Device | - |
CanvasDevice |
ID2D1Device1 |
- | - |
CanvasDrawingSession |
ID2D1DeviceContext1 |
- | - |
CanvasFontFace |
IDWriteFontFaceReference |
- | - |
CanvasFontSet |
IDWriteFontSet |
- | - |
CanvasGeometry |
ID2D1Geometry, eller något av dess härledda gränssnitt ID2D1PathGeometry, ID2D1RectangleGeometry, ID2D1RoundedRectangleGeometry, ID2D1EllipseGeometry, ID2D1TransformedGeometryeller ID2D1GeometryGroup |
Device | - |
CanvasGradientMesh |
ID2D1GradientMesh |
Device | - |
CanvasImageBrush |
ID2D1BitmapBrush1 (om bilden är en CanvasBitmap och SourceRectangle är null) eller ID2D1ImageBrush (om det är någon annan typ av ICanvasImage, eller om SourceRectangle is set) |
Device | Valfritt DPI^1 |
CanvasLinearGradientBrush |
ID2D1LinearGradientBrush |
Device | - |
CanvasNumberSubstitution |
IDWriteNumberSubstitution |
- | - |
CanvasRadialGradientBrush |
ID2D1RadialGradientBrush |
Device | - |
CanvasRenderTarget |
ID2D1Bitmap1 med D2D1_BITMAP_OPTIONS_TARGET |
Device | - |
CanvasSolidColorBrush |
ID2D1SolidColorBrush |
Device | - |
CanvasStrokeStyle |
ID2D1StrokeStyle1 |
- | Device |
CanvasSvgDocument |
ID2D1SvgDocument^2 |
Device | - |
CanvasSwapChain |
IDXGISwapChain1 |
Enhet, DPI | - |
CanvasTextFormat |
IDWriteTextFormat1 |
- | - |
CanvasTextLayout |
IDWriteTextLayout3 |
Device | - |
CanvasTextRenderingParameters |
IDWriteRenderingParams3 |
- | - |
CanvasTypography |
IDWriteTypography |
- | - |
CanvasVirtualBitmap |
ID2D1ImageSource eller ID2D1TransformedImageSource |
Device | - |
ColorManagementProfile |
ID2D1ColorContext |
Device | Device |
EffectTransferTable3D |
ID2D1LookupTable3D |
Device | - |
Microsoft.Graphics.Canvas.Effects.* (flera Win2D-klasser mappas till samma D2D-typ) |
ID2D1Effect med lämplig D2D1_PROPERTY_TYPE_CLSID |
Device | Enhet, DPI som tillval^1 |
Note
^1: valfritt DPI innebär att det är giltigt att anropa GetWrappedResource den här typen utan att ange ett DPI-värde, men om du anger DPI kan Win2D kanske mer effektivt konfigurera effektdiagram genom att utelämna redundanta DPI-kompensationsnoder. Detta gäller när du anropar GetWrappedResource en effekt, eller på en CanvasImageBrush som har en effekt som källbild.
Note
^2: när en CanvasSvgDocument skapas från en ID2D1SvgDocument med inbyggt C++-interop ignoreras storleken på ID2D1SvgDocuments visningsområde.
Interop med C++/CX
Här är ett exempel på hur Win2D kan samverka med Direct2D med hjälp av C++:
#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
Interop är också möjligt via C#, på olika sätt (t.ex. med inbyggda COM/WinRT-interop, via CsWinRT:s API:er eller med hjälp av blittable-bindningar). Mer information om manuell interop i C#finns i dokumenten om CsWinRT.
Interoperabilitet med C++/WinRT
Du kan också utföra interop med C++/WinRT med viss ändring av ovanstående. Observera att C++/WinRT-huvudena för Win2D-Windows Runtime-komponenter ska genereras automatiskt när du lägger till Win2D NuGet-paketet i ditt C++/WinRT-projekt. För interop behöver du dock fortfarande använda huvudfilen Microsoft. Graphics.Canvas.native.h som innehåller ABI-gränssnittet ICanvasFactoryNative på låg nivå i namnområdet ABI::Microsoft::Graphics::Canvas. Gränssnittet har följande funktioner som du kan använda för att utföra interop.
HRESULT GetOrCreate(ICanvasDevice* device, IUnknown* resource, float dpi, IInspectable** wrapper);
HRESULT GetNativeResource(ICanvasDevice* device, float dpi, REFIID iid, void** resource);
Här är ett exempel som visar hur du skapar en CanvasVirtualBitmap från en IWICBitmapSource, med början i IWICBitmapSource och den delade CanvasDevice.
#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;
}
}
Kom ihåg att inkludera rubriken <unknwn.h> i pch.h före alla WinRT-huvuden (krävs i SDK 17763 och senare).
Windows developer