Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Win2D est implémenté en tant que couche sur Direct2D et prend en charge l’interopérabilité dans les deux sens. Si vous avez un objet Win2D, vous pouvez accéder à l’objet Direct2D natif utilisé pour l’implémenter. Si vous avez un objet Direct2D, vous pouvez rechercher l’objet Win2D qui l’encapsule, ou créer un wrapper s’il n’en existe pas déjà un.
L’interopérabilité vous permet de combiner et de mettre en correspondance Win2D avec des API DirectX natives. Vous pouvez écrire une application qui utilise principalement Win2D, tout en pouvant revenir à DirectX natif à tout moment, par exemple pour faire appel à une autre API ou à un composant tiers qui nécessite des interfaces natives. Ou votre application peut être essentiellement une application DirectX native, tout en vous permettant de passer à Win2D à certains endroits où vous souhaitez bénéficier de sa plus grande simplicité d’utilisation ou de la prise en charge de C#.
API d’interopérabilité
Les API d’interopérabilité C++/CX sont définies dans l’en-tête Microsoft. Graphics.Canvas.native.h :
#include <Microsoft.Graphics.Canvas.native.h>
using namespace Microsoft::Graphics::Canvas;
Pour obtenir l’objet Direct2D natif encapsulé par un objet 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);
Pour la plupart des types GetWrappedResource , il est possible d’appeler uniquement un objet wrapper Win2D en tant que paramètre. Pour quelques types (voir le tableau ci-dessous), il faut également fournir un appareil et/ou une valeur DPI. Il n'est pas considéré comme une erreur de transmettre un appareil ou un DPI lors de l'utilisation de GetWrappedResource avec des types qui n'en ont pas besoin.
Pour obtenir un objet Win2D encapsulant un objet Direct2D natif :
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 retourne une instance de wrapper existante si une instance existe déjà, ou crée un wrapper si ce n’est pas le cas. L’appel répété sur le même objet natif retourne le même wrapper chaque fois, tant que cette instance de wrapper continue d’exister. Si toutes les références à l’encapsuleur sont libérées au point que son nombre de références tombe à zéro et qu’il soit détruit, tout appel ultérieur à GetOrCreate devra créer un nouvel encapsuleur.
Pour certains types, il est possible d’appeler GetOrCreate avec comme seul paramètre un objet de ressource Direct2D, tandis que pour d’autres types (voir le tableau ci-dessous), il faut également lui passer un périphérique et une valeur de PPP (DPI). Il n'est pas considéré comme une erreur de transmettre un appareil ou un DPI lors de l'utilisation de GetOrCreate avec des types qui n'en ont pas besoin. Si un wrapper Win2D existe déjà, il est possible d’omettre le périphérique et le DPI, même pour les types qui en auraient normalement besoin : ces paramètres ne sont utilisés que lors de la création de nouvelles instances de wrapper.
GetOrCreate comprend les hiérarchies d’héritage et crée toujours le type de wrapper le plus dérivé approprié. Par exemple, si vous appelez GetOrCreate<CanvasBitmap>(ID2D1Bitmap1*) avec un ID2D1Bitmap1 portant l’indicateur D2D1_BITMAP_OPTIONS_TARGET, l’instance wrapper retournée sera en fait de type CanvasRenderTarget (qui dérive de CanvasBitmap). À l'inverse, si vous appelez GetOrCreate<CanvasRenderTarget>(ID2D1Bitmap1*) avec un ID2D1Bitmap1 qui ne possède pas D2D1_BITMAP_OPTIONS_TARGET, une exception de transtypage non valide est levée.
En prenant cela à l’extrême, il est valide d’appeler GetOrCreate<Object>(IUnknown*), et aussi GetWrappedResource<IUnknown>(Object^).
Types qui prennent en charge l’interopérabilité
| Type Win2D | Type Direct2D | Paramètres GetOrCreate |
Paramètres GetWrappedResource |
|---|---|---|---|
CanvasBitmap |
ID2D1Bitmap1 sans D2D1_BITMAP_OPTIONS_TARGET |
Device | - |
CanvasCachedGeometry |
ID2D1GeometryRealization |
Device | - |
CanvasCommandList |
ID2D1CommandList |
Device | - |
CanvasDevice |
ID2D1Device1 |
- | - |
CanvasDrawingSession |
ID2D1DeviceContext1 |
- | - |
CanvasFontFace |
IDWriteFontFaceReference |
- | - |
CanvasFontSet |
IDWriteFontSet |
- | - |
CanvasGeometry |
ID2D1Geometryou l’une de ses interfaces ID2D1PathGeometrydérivées, ID2D1RectangleGeometry, ID2D1RoundedRectangleGeometry, ID2D1EllipseGeometry, ID2D1TransformedGeometryou ID2D1GeometryGroup |
Device | - |
CanvasGradientMesh |
ID2D1GradientMesh |
Device | - |
CanvasImageBrush |
ID2D1BitmapBrush1 (si l’image est un CanvasBitmap et SourceRectangle est null) ou ID2D1ImageBrush (s’il s’agit de tout autre type de ICanvasImage, ou si SourceRectangle is set) |
Device | DPI facultatif^1 |
CanvasLinearGradientBrush |
ID2D1LinearGradientBrush |
Device | - |
CanvasNumberSubstitution |
IDWriteNumberSubstitution |
- | - |
CanvasRadialGradientBrush |
ID2D1RadialGradientBrush |
Device | - |
CanvasRenderTarget |
ID2D1Bitmap1 avec D2D1_BITMAP_OPTIONS_TARGET |
Device | - |
CanvasSolidColorBrush |
ID2D1SolidColorBrush |
Device | - |
CanvasStrokeStyle |
ID2D1StrokeStyle1 |
- | Device |
CanvasSvgDocument |
ID2D1SvgDocument^2 |
Device | - |
CanvasSwapChain |
IDXGISwapChain1 |
Appareil, PPP | - |
CanvasTextFormat |
IDWriteTextFormat1 |
- | - |
CanvasTextLayout |
IDWriteTextLayout3 |
Device | - |
CanvasTextRenderingParameters |
IDWriteRenderingParams3 |
- | - |
CanvasTypography |
IDWriteTypography |
- | - |
CanvasVirtualBitmap |
ID2D1ImageSource ou ID2D1TransformedImageSource |
Device | - |
ColorManagementProfile |
ID2D1ColorContext |
Device | Device |
EffectTransferTable3D |
ID2D1LookupTable3D |
Device | - |
Microsoft.Graphics.Canvas.Effects.* (plusieurs classes Win2D correspondent au même type D2D) |
ID2D1Effect avec le D2D1_PROPERTY_TYPE_CLSID approprié |
Device | Appareil, DPI facultatif^1 |
Note
^1 : DPI facultatif signifie qu’il est possible d’appeler GetWrappedResource pour ce type sans spécifier de valeur DPI, mais si vous indiquez une valeur DPI, Win2D pourra peut-être configurer plus efficacement les graphes d’effets en omettant les nœuds redondants de compensation DPI. Cela s'applique lorsque vous appelez GetWrappedResource sur un effet, ou sur un CanvasImageBrush dont l'image source est un effet.
Note
^2 : lorsqu’un CanvasSvgDocument est produit à partir d’un ID2D1SvgDocument à l’aide de l’interopérabilité C++ native, la taille de la fenêtre d’affichage du ID2D1SvgDocument est ignorée.
Interopérabilité à l’aide de C++/CX
Voici un exemple de la façon dont Win2D peut interagir avec Direct2D à l’aide de 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
L'interopérabilité est également possible via C#, par différents moyens (par exemple en utilisant l'interopérabilité COM/WinRT intégrée, les API de CsWinRT ou des liaisons blittables). Pour plus d’informations sur l’interopérabilité manuelle en C#, reportez-vous à la documentation sur CsWinRT.
Interopérabilité à l’aide de C++/WinRT
Vous pouvez également réaliser l’interopérabilité à l’aide de C++/WinRT, moyennant quelques modifications de ce qui précède. Notez que les en-têtes C++/WinRT pour les composants Win2D Windows Runtime doivent être générés automatiquement lorsque vous ajoutez le package NuGet Win2D à votre projet C++/WinRT. Toutefois, pour l’interopérabilité, vous devez toujours utiliser le fichier d’en-tête Microsoft. Graphics.Canvas.native.h qui contient l’interface ICanvasFactoryNative ABI de bas niveau dans l’espace de noms ABI::Microsoft::Graphics::Canvas. L’interface a les fonctions suivantes que vous pouvez utiliser pour effectuer l’interopérabilité.
HRESULT GetOrCreate(ICanvasDevice* device, IUnknown* resource, float dpi, IInspectable** wrapper);
HRESULT GetNativeResource(ICanvasDevice* device, float dpi, REFIID iid, void** resource);
Voici un exemple montrant comment créer un CanvasVirtualBitmap à partir d’un IWICBitmapSource, en commençant par le IWICBitmapSource et le CanvasDevice partagé.
#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;
}
}
N’oubliez pas d’inclure l’en-tête <unknwn.h> dans pch.h avant tous les en-têtes WinRT (requis dans le SDK 17763 et versions ultérieures).
Windows developer