início rápido do Direct2D para Windows 8
Direct2D é uma API de código nativo e modo imediato para criar gráficos 2D. Este tópico ilustra como usar Direct2D para desenhar em um Windows::UI::Core::CoreWindow.
Este tópico contém as seguintes seções:
- Desenhando um retângulo simples
- Etapa 1: incluir Direct2D cabeçalho
- Etapa 2: Criar um ID2D1Factory1
- Etapa 3: Criar um ID2D1Device e um ID2D1DeviceContext
- Etapa 4: Criar um pincel
- Etapa 5: Desenhar o retângulo
- Código de exemplo
Desenhando um retângulo simples
Para desenhar um retângulo usando GDI, você pode manipular a mensagem WM_PAINT , conforme mostrado no código a seguir.
switch(message)
{
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
// Obtain the size of the drawing area.
RECT rc;
GetClientRect(
hwnd,
&rc
);
// Save the original object
HGDIOBJ original = NULL;
original = SelectObject(
ps.hdc,
GetStockObject(DC_PEN)
);
// Create a pen.
HPEN blackPen = CreatePen(PS_SOLID, 3, 0);
// Select the pen.
SelectObject(ps.hdc, blackPen);
// Draw a rectangle.
Rectangle(
ps.hdc,
rc.left + 100,
rc.top + 100,
rc.right - 100,
rc.bottom - 100);
DeleteObject(blackPen);
// Restore the original object
SelectObject(ps.hdc, original);
EndPaint(hwnd, &ps);
}
return 0;
// Code for handling other messages.
O código para desenhar o mesmo retângulo com Direct2D é semelhante: ele cria recursos de desenho, descreve uma forma a ser desenhada, desenha a forma e libera os recursos de desenho. As seções a seguir descrevem cada uma dessas etapas em detalhes.
Etapa 1: incluir Direct2D cabeçalho
Além dos cabeçalhos necessários para o aplicativo, inclua os cabeçalhos d2d1.h e d2d1_1.h.
Etapa 2: Criar um ID2D1Factory1
Uma das primeiras coisas que qualquer exemplo Direct2D faz é criar um ID2D1Factory1.
DX::ThrowIfFailed(
D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
__uuidof(ID2D1Factory1),
&options,
&m_d2dFactory
)
);
A interface ID2D1Factory1 é o ponto de partida para usar Direct2D; use um ID2D1Factory1 para criar recursos Direct2D.
Ao criar uma fábrica, você pode especificar se ela é multi-ou de thread único. (Para obter mais informações sobre fábricas multi-threaded, consulte os comentários na página de referência ID2D1Factory.) Este exemplo cria uma fábrica de thread único.
Em geral, seu aplicativo deve criar a fábrica uma vez e retê-la durante a vida útil do aplicativo.
Etapa 3: Criar um ID2D1Device e um ID2D1DeviceContext
Depois de criar uma fábrica, use-a para criar um dispositivo Direct2D e, em seguida, use o dispositivo para criar um contexto de dispositivo Direct2D. Para criar esses objetos Direct2D, você deve ter um dispositivo Direct3D 11, um dispositivo DXGI e uma cadeia de troca DXGI. Consulte Dispositivos e Contextos de Dispositivo para obter informações sobre como criar os pré-requisitos necessários.
// Obtain the underlying DXGI device of the Direct3D11.1 device.
DX::ThrowIfFailed(
m_d3dDevice.As(&dxgiDevice)
);
// Obtain the Direct2D device for 2-D rendering.
DX::ThrowIfFailed(
m_d2dFactory->CreateDevice(dxgiDevice.Get(), &m_d2dDevice)
);
// And get its corresponding device context object.
DX::ThrowIfFailed(
m_d2dDevice->CreateDeviceContext(
D2D1_DEVICE_CONTEXT_OPTIONS_NONE,
&m_d2dContext
)
);
Um contexto de dispositivo é um dispositivo que pode executar operações de desenho e criar recursos de desenho dependentes do dispositivo, como pincéis. Você também usa o contexto do dispositivo para vincular um ID2D1Bitmap a uma superfície DXGI para usar como um destino de renderização. O contexto do dispositivo pode renderizar para diferentes tipos de destinos.
O código aqui declara as propriedades do bitmap que se vinculam a uma cadeia de troca DXGI que é renderizada para um CoreWindow. O método ID2D1DeviceContext::CreateBitmapFromDxgiSurface obtém uma superfície Direct2D da superfície DXGI. Isso faz com que qualquer coisa renderizada para o ID2D1Bitmap de destino seja renderizada para a superfície da cadeia de troca.
Depois de ter a superfície Direct2D, use o método ID2D1DeviceContext::SetTarget para defini-lo como o destino de renderização ativo.
// Now we set up the Direct2D render target bitmap linked to the swapchain.
// Whenever we render to this bitmap, it will be directly rendered to the
// swapchain associated with the window.
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
m_dpi,
m_dpi
);
// Direct2D needs the dxgi version of the backbuffer surface pointer.
ComPtr<IDXGISurface> dxgiBackBuffer;
DX::ThrowIfFailed(
m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
);
// Get a D2D surface from the DXGI back buffer to use as the D2D render target.
DX::ThrowIfFailed(
m_d2dContext->CreateBitmapFromDxgiSurface(
dxgiBackBuffer.Get(),
&bitmapProperties,
&m_d2dTargetBitmap
)
);
// So now we can set the Direct2D render target.
m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());
Etapa 4: Criar um pincel
Como uma fábrica, um contexto de dispositivo pode criar recursos de desenho. Neste exemplo, o contexto do dispositivo cria um pincel.
ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
m_d2dContext->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush
)
);
Um pincel é um objeto que pinta uma área, como o traço de uma forma ou o preenchimento de uma geometria. O pincel neste exemplo pinta uma área com uma cor sólida predefinida, preto.
Direct2D também fornece outros tipos de pincéis: pincéis de gradiente para pintar gradientes lineares e radiais, um pincel de bitmap para pintura com bitmaps e padrões, e começando em Windows 8, um pincel de imagem para pintura com uma imagem renderizada.
Algumas APIs de desenho fornecem canetas para contornos de desenho e pincéis para preencher formas. Direct2D é diferente: ele não fornece um objeto de caneta, mas usa um pincel para desenhar contornos e preencher formas. Ao desenhar estruturas de tópicos, use a interface ID2D1StrokeStyle ou começando no Windows 8 interface ID2D1StrokeStyle1, com um pincel para controlar as operações de acariciamento de caminho.
Um pincel só pode ser usado com o destino de renderização que o criou e com outros destinos de renderização no mesmo domínio de recurso. Em geral, você deve criar pincéis uma vez e retê-los durante a vida útil do destino de renderização que os criou. ID2D1SolidColorBrush é a exceção solitária; porque é relativamente barato criar, você pode criar um ID2D1SolidColorBrush sempre que desenhar um quadro, sem nenhum impacto perceptível no desempenho. Você também pode usar um único ID2D1SolidColorBrush e apenas alterar sua cor ou opacidade sempre que usá-lo.
Etapa 5: Desenhar o retângulo
Em seguida, use o contexto do dispositivo para desenhar o retângulo.
m_d2dContext->BeginDraw();
m_d2dContext->DrawRectangle(
D2D1::RectF(
rc.left + 100.0f,
rc.top + 100.0f,
rc.right - 100.0f,
rc.bottom - 100.0f),
pBlackBrush);
DX::ThrowIfFailed(
m_d2dContext->EndDraw()
);
DX::ThrowIfFailed(
m_swapChain->Present1(1, 0, ¶meters);
);
O método DrawRectangle usa dois parâmetros: o retângulo a ser desenhado e o pincel a ser usado para pintar a estrutura de tópicos do retângulo. Opcionalmente, você também pode especificar as opções largura do traço, padrão de traço, junção de linha e limite final.
Você deve chamar o método BeginDraw antes de emitir comandos de desenho e deve chamar o método EndDraw depois de terminar de emitir comandos de desenho. O método EndDraw retorna um HRESULT que indica se os comandos de desenho foram bem-sucedidos. Se não for bem-sucedida, a função auxiliar ThrowIfFailed gerará uma exceção.
O método IDXGISwapChain::P resent troca a superfície do buffer pela superfície da tela para exibir o resultado.
Código de exemplo
O código neste tópico mostra os elementos básicos de um aplicativo Direct2D. Para resumir, o tópico omite a estrutura do aplicativo e o código de tratamento de erros que são características de um aplicativo bem escrito.