Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O Win2D é implementado como uma camada na parte superior do Direct2D e dá suporte à interoperabilidade em ambas as direções. Se você tiver um objeto Win2D, poderá acessar o objeto Direct2D nativo usado para implementá-lo. Se você tiver um objeto Direct2D, poderá procurar o objeto Win2D que o encapsula ou criar um novo wrapper se ainda não existir um.
A interoperabilidade permite combinar o Win2D com APIs nativas do DirectX. Você pode escrever um aplicativo que usa principalmente o Win2D, mas cair para o DirectX nativo a qualquer momento - talvez para chamar alguma outra API ou componente de terceiros que exija interfaces nativas. Ou seu aplicativo pode ser principalmente directX nativo, mas você pode mudar para o Win2D em locais específicos em que você deseja sua conveniência extra ou suporte a C#.
APIs de interoperabilidade
As APIs de interoperabilidade C++/CX são definidas no cabeçalho Microsoft. Graphics.Canvas.native.h:
#include <Microsoft.Graphics.Canvas.native.h>
using namespace Microsoft::Graphics::Canvas;
Para obter o objeto Direct2D nativo que é encapsulado por um objeto 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);
Para a maioria dos tipos, GetWrappedResource pode ser chamado tendo como parâmetro apenas um objeto encapsulador do Win2D. Para alguns tipos (conforme a tabela abaixo), também é necessário informar um dispositivo e/ou um valor de DPI. Não é um erro passar um dispositivo ou DPI ao usar GetWrappedResource com tipos que não os exigem.
Para obter um objeto Win2D encapsulando um objeto 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 retornará uma instância de wrapper existente se já existir ou criará um novo wrapper se não existir. Chamar repetidamente no mesmo objeto nativo retornará o mesmo wrapper a cada vez, desde que essa instância do wrapper continue a existir. Se todas as referências ao wrapper forem liberadas, de modo que sua contagem de referências chegue a zero e ele seja destruído, qualquer chamada posterior a GetOrCreate terá de criar um novo wrapper.
Para alguns tipos, GetOrCreate pode ser chamado apenas com um objeto de recurso do Direct2D como parâmetro, enquanto, para outros tipos (veja a tabela abaixo), também devem ser informados um dispositivo e um valor de DPI. Não é um erro passar um dispositivo ou DPI ao usar GetOrCreate com tipos que não os exigem. Se já existir um wrapper Win2D, não há problema em omitir o dispositivo e o DPI mesmo para tipos que normalmente precisariam deles: esses parâmetros são usados apenas ao criar novas instâncias de wrapper.
GetOrCreate entende hierarquias de herança e sempre criará o tipo wrapper mais derivado apropriado. Por exemplo, se você chamar GetOrCreate<CanvasBitmap>(ID2D1Bitmap1*) com um ID2D1Bitmap1 que tenha o sinalizador D2D1_BITMAP_OPTIONS_TARGET, a instância wrapper retornada será, de fato, uma CanvasRenderTarget (que deriva de CanvasBitmap). Por outro lado, se você chamar GetOrCreate<CanvasRenderTarget>(ID2D1Bitmap1*) com um ID2D1Bitmap1 que não tem D2D1_BITMAP_OPTIONS_TARGET, isso lançará uma exceção de conversão inválida.
Levando isso ao extremo, é válido chamar GetOrCreate<Object>(IUnknown*)e também GetWrappedResource<IUnknown>(Object^).
Tipos que dão suporte à interoperabilidade
| Tipo Win2D | Tipo Direct2D | Parâmetros GetOrCreate |
Parâmetros GetWrappedResource |
|---|---|---|---|
CanvasBitmap |
ID2D1Bitmap1 Sem D2D1_BITMAP_OPTIONS_TARGET |
Device | - |
CanvasCachedGeometry |
ID2D1GeometryRealization |
Device | - |
CanvasCommandList |
ID2D1CommandList |
Device | - |
CanvasDevice |
ID2D1Device1 |
- | - |
CanvasDrawingSession |
ID2D1DeviceContext1 |
- | - |
CanvasFontFace |
IDWriteFontFaceReference |
- | - |
CanvasFontSet |
IDWriteFontSet |
- | - |
CanvasGeometry |
ID2D1Geometry, ou uma de suas interfaces derivadas ID2D1PathGeometry, ID2D1RectangleGeometry, ID2D1RoundedRectangleGeometry, ID2D1EllipseGeometry, ID2D1TransformedGeometry ou ID2D1GeometryGroup |
Device | - |
CanvasGradientMesh |
ID2D1GradientMesh |
Device | - |
CanvasImageBrush |
ID2D1BitmapBrush1 (se a imagem for um CanvasBitmap e SourceRectangle for null) ou ID2D1ImageBrush (se for qualquer outro tipo de ICanvasImage, ou se SourceRectangle is set) |
Device | DPI opcional^1 |
CanvasLinearGradientBrush |
ID2D1LinearGradientBrush |
Device | - |
CanvasNumberSubstitution |
IDWriteNumberSubstitution |
- | - |
CanvasRadialGradientBrush |
ID2D1RadialGradientBrush |
Device | - |
CanvasRenderTarget |
ID2D1Bitmap1 por D2D1_BITMAP_OPTIONS_TARGET |
Device | - |
CanvasSolidColorBrush |
ID2D1SolidColorBrush |
Device | - |
CanvasStrokeStyle |
ID2D1StrokeStyle1 |
- | Device |
CanvasSvgDocument |
ID2D1SvgDocument^2 |
Device | - |
CanvasSwapChain |
IDXGISwapChain1 |
Dispositivo, DPI | - |
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.* (várias classes Win2D são mapeadas para o mesmo tipo D2D) |
ID2D1Effect com o D2D1_PROPERTY_TYPE_CLSID apropriado |
Device | Dispositivo, DPI opcional^1 |
Note
^1: DPI opcional significa que é válido chamar GetWrappedResource para esse tipo sem especificar um valor de DPI, mas, se você especificar um valor de DPI, o Win2D poderá configurar grafos de efeitos com mais eficiência, omitindo nós redundantes de compensação de DPI. Isso se aplica ao chamar GetWrappedResource em um efeito ou em um CanvasImageBrush que tem um efeito como sua imagem de origem.
Note
^2: quando um CanvasSvgDocument é produzido a partir de um ID2D1SvgDocument usando interoperabilidade nativa de C++, o tamanho da viewport do ID2D1SvgDocument é ignorado.
Interoperabilidade usando C++/CX
Aqui está um exemplo de como o Win2D pode interoperar com o 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());
Note
A interoperabilidade também é possível via C#, por diversos meios (por exemplo, usando a interoperabilidade COM/WinRT integrada, por meio das APIs do CsWinRTou usando vinculações blittable). Para obter mais informações sobre a interoperabilidade manual em C#, consulte os documentos sobre CsWinRT.
Interoperabilidade usando C++/WinRT
Você também pode realizar a interoperabilidade usando C++/WinRT com algumas modificações do descrito acima. Observe que os cabeçalhos C++/WinRT para os Componentes de Windows Runtime win2D devem ser gerados automaticamente quando você adiciona o pacote NuGet Win2D ao seu projeto C++/WinRT. No entanto, para interoperabilidade, você ainda precisará usar o arquivo de cabeçalho Microsoft. Graphics.Canvas.native.h que contém a interface ICanvasFactoryNative ABI de baixo nível no namespaceABI::Microsoft::Graphics::Canvas. A interface tem as seguintes funções, que você pode usar para realizar a interoperabilidade.
HRESULT GetOrCreate(ICanvasDevice* device, IUnknown* resource, float dpi, IInspectable** wrapper);
HRESULT GetNativeResource(ICanvasDevice* device, float dpi, REFIID iid, void** resource);
Aqui está um exemplo que mostra como criar um CanvasVirtualBitmap a partir de um IWICBitmapSource, começando com o IWICBitmapSource e o CanvasDevice compartilhado.
#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;
}
}
Lembre-se de incluir o cabeçalho <unknwn.h> em pch.h antes de qualquer cabeçalho WinRT (necessário no SDK 17763 e posterior).
Windows developer