Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Win2D viene implementato come livello sopra Direct2De supporta l'interoperabilità in entrambe le direzioni. Se si dispone di un oggetto Win2D, è possibile accedere all'oggetto Direct2D nativo usato per implementarlo. Se si dispone di un oggetto Direct2D, è possibile cercare l'oggetto Win2D che esegue il wrapping oppure creare un nuovo wrapper, se non ne esiste già uno.
L'interoperabilità consente di combinare e associare Win2D alle API DirectX native. È possibile scrivere un'app che usa principalmente Win2D, ma passare a DirectX nativo in qualsiasi momento, ad esempio per richiamare un'altra API o un componente di terze parti che richiede interfacce native. In alternativa, la tua app può essere principalmente nativa DirectX, ma puoi passare a Win2D in posizioni specifiche in cui vuoi il supporto aggiuntivo o C#.
API di interoperabilità
Le API di interoperabilità C++/CX sono definite nell'intestazione Microsoft.Graphics.Canvas.native.h:
#include <Microsoft.Graphics.Canvas.native.h>
using namespace Microsoft::Graphics::Canvas;
Per ottenere l'oggetto Direct2D nativo incapsulato in un oggetto Win2D:
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);
Per la maggior parte dei tipi GetWrappedResource può essere chiamato con solo un oggetto wrapper Win2D come parametro. Per alcuni tipi (vedi tabella sotto), è necessario passare anche un dispositivo e/o un valore DPI. Non è un errore specificare un dispositivo o un DPI quando si usa GetWrappedResource con tipi che non li richiedono.
Per ottenere un oggetto Win2D che esegue il wrapping di un oggetto Direct2D nativo:
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 restituisce un'istanza del wrapper esistente se ne esiste già una o crea un nuovo wrapper, se non ne esiste uno. La chiamata ripetuta sullo stesso oggetto nativo restituirà ogni volta lo stesso wrapper, purché l'istanza del wrapper continui a esistere. Se tutti i riferimenti al wrapper vengono rilasciati in modo che il conteggio dei riferimenti vada a zero e venga eliminato definitivamente, qualsiasi chiamata successiva a GetOrCreate dovrà creare un nuovo wrapper.
Per alcuni tipi GetOrCreate può essere chiamato con solo un oggetto risorsa Direct2D come parametro, mentre per altri tipi (vedere la tabella seguente) deve essere passato anche un dispositivo e un valore DPI. Non è un errore specificare un dispositivo o un DPI quando si usa GetOrCreate con tipi che non li richiedono. Se esiste già un wrapper Win2D, è possibile omettere il dispositivo e la dpi anche per i tipi che normalmente ne sarebbero necessari: questi parametri vengono usati solo quando si creano nuove istanze wrapper.
GetOrCreate comprende le gerarchie di ereditarietà e creerà sempre il tipo wrapper più derivato appropriato. Ad esempio, se si chiama GetOrCreate<CanvasBitmap>(ID2D1Bitmap1*) con un ID2D1Bitmap1 che presenta il flag D2D1_BITMAP_OPTIONS_TARGET, l'istanza wrapper restituita sarà in realtà un CanvasRenderTarget (che deriva da CanvasBitmap). In alternativa, se si chiama GetOrCreate<CanvasRenderTarget>(ID2D1Bitmap1*) con un oggetto ID2D1Bitmap1 che non dispone di D2D1_BITMAP_OPTIONS_TARGET, verrà generata un'eccezione di cast non valida.
Se si esegue questa operazione all'estrema, è possibile chiamare GetOrCreate<Object>(IUnknown*)e anche GetWrappedResource<IUnknown>(Object^).
Tipi che supportano l'interoperabilità
| Tipo Win2D | Tipo Direct2D |
GetOrCreate parametri |
GetWrappedResource parametri |
|---|---|---|---|
CanvasBitmap |
ID2D1Bitmap1 senza D2D1_BITMAP_OPTIONS_TARGET |
Dispositivo | - |
CanvasCachedGeometry |
ID2D1GeometryRealization |
Dispositivo | - |
CanvasCommandList |
ID2D1CommandList |
Dispositivo | - |
CanvasDevice |
ID2D1Device1 |
- | - |
CanvasDrawingSession |
ID2D1DeviceContext1 |
- | - |
CanvasFontFace |
IDWriteFontFaceReference |
- | - |
CanvasFontSet |
IDWriteFontSet |
- | - |
CanvasGeometry |
ID2D1Geometryo una delle interfacce derivate ID2D1PathGeometry, ID2D1RectangleGeometry, ID2D1RoundedRectangleGeometry, ID2D1EllipseGeometry, ID2D1TransformedGeometryo ID2D1GeometryGroup |
Dispositivo | - |
CanvasGradientMesh |
ID2D1GradientMesh |
Dispositivo | - |
CanvasImageBrush |
ID2D1BitmapBrush1 (se l'immagine è un CanvasBitmap e SourceRectangle è null) o ID2D1ImageBrush (se è qualsiasi altro tipo di ICanvasImageo se SourceRectangle is set) |
Dispositivo | DPI^1 opzionale |
CanvasLinearGradientBrush |
ID2D1LinearGradientBrush |
Dispositivo | - |
CanvasNumberSubstitution |
IDWriteNumberSubstitution |
- | - |
CanvasRadialGradientBrush |
ID2D1RadialGradientBrush |
Dispositivo | - |
CanvasRenderTarget |
ID2D1Bitmap1 con D2D1_BITMAP_OPTIONS_TARGET |
Dispositivo | - |
CanvasSolidColorBrush |
ID2D1SolidColorBrush |
Dispositivo | - |
CanvasStrokeStyle |
ID2D1StrokeStyle1 |
- | Dispositivo |
CanvasSvgDocument |
ID2D1SvgDocument^2 |
Dispositivo | - |
CanvasSwapChain |
IDXGISwapChain1 |
Dispositivo, DPI | - |
CanvasTextFormat |
IDWriteTextFormat1 |
- | - |
CanvasTextLayout |
IDWriteTextLayout3 |
Dispositivo | - |
CanvasTextRenderingParameters |
IDWriteRenderingParams3 |
- | - |
CanvasTypography |
IDWriteTypography |
- | - |
CanvasVirtualBitmap |
ID2D1ImageSource oppure ID2D1TransformedImageSource |
Dispositivo | - |
ColorManagementProfile |
ID2D1ColorContext |
Dispositivo | Dispositivo |
EffectTransferTable3D |
ID2D1LookupTable3D |
Dispositivo | - |
Microsoft.Graphics.Canvas.Effects.* (più classi Win2D mappano allo stesso tipo D2D) |
ID2D1Effect con l'oggetto appropriato D2D1_PROPERTY_TYPE_CLSID |
Dispositivo | Dispositivo, DPI^1 opzionale |
Nota
^1: DPI facoltativo significa che è valido chiamare GetWrappedResource per questo tipo senza specificare un valore DPI, ma se si specifica DPI, Win2D può essere in grado di configurare in modo più efficiente i grafici degli effetti lasciando i nodi di compensazione DPI ridondanti. Questo vale quando si chiama GetWrappedResource su un effetto o su un oggetto CanvasImageBrush che ha un effetto come immagine di origine.
Nota
^2: quando un CanvasSvgDocument viene creato da un ID2D1SvgDocument tramite interoperabilità C++ nativa, le dimensioni del viewport di ID2D1SvgDocument vengono ignorate.
Interoperabilità con C++/CX
Ecco un esempio di come Win2D può interagire con Direct2D, usando 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());
Nota
L'interoperabilità è possibile anche tramite C#, in vari modi (ad esempio usando l'interoperabilità COM/WinRT integrata, tramite le API di CsWinRT o usando binding blittable). Per altre informazioni sull'interoperabilità manuale in C#, vedere la documentazione su CsWinRT.
Interoperabilità con C++/WinRT
È anche possibile eseguire l'interoperabilità usando C++/WinRT con alcune modifiche apportate in precedenza. Si noti che le intestazioni C++/WinRT per i componenti Windows Runtime Win2D devono essere generate automaticamente quando si aggiunge il pacchetto NuGet Win2D al progetto C++/WinRT. Tuttavia, per l'interoperabilità sarà comunque necessario usare il file di intestazione Microsoft.Graphics.Canvas.native.h che contiene l'interfaccia ABI ICanvasFactoryNative di basso livello nello spazio dei nomi ABI::Microsoft::Graphics::Canvas. L'interfaccia include le funzioni seguenti che è possibile usare per eseguire l'interoperabilità.
HRESULT GetOrCreate(ICanvasDevice* device, IUnknown* resource, float dpi, IInspectable** wrapper);
HRESULT GetNativeResource(ICanvasDevice* device, float dpi, REFIID iid, void** resource);
Ecco un esempio che mostra come creare un CanvasVirtualBitmap da un IWICBitmapSource a partire dal IWICBitmapSource e dal CanvasDevice condiviso.
#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;
}
}
Ricordarsi di includere l'intestazione <unknwn.h> in pch.h prima di qualsiasi intestazione WinRT (richiesta in SDK 17763 e versioni successive).