Aqui, examinaremos o código para a criação de uma janela de renderização 2D usando Direct2D, incluindo uma análise detalhada de cada parte do código e uma explicação sobre a função GeometrySink no contexto de criação de formas complexas.
Estrutura do Código
O código de criação da janela de renderização é dividido nas seguintes partes principais:
- Definições de Variáveis Globais
- Função InitDirect2D para Inicializar o Direct2D
- Função WndProc para o Procedimento de Janela
- Função Render para Desenho dos Elementos 2D
- Função Cleanup para Liberação de Recursos
1. Definições de Variáveis Globais
Aqui definimos variáveis globais para os principais componentes do Direct2D:
ID2D1Factory* pFactory = nullptr; // Fábrica Direct2D
ID2D1HwndRenderTarget* pRenderTarget = nullptr; // Superfície de renderização para a janela
ID2D1SolidColorBrush* pBrushBlack = nullptr; // Pincel para a cor preta
ID2D1SolidColorBrush* pBrushRed = nullptr; // Pincel para a cor vermelha
ID2D1SolidColorBrush* pBrushGreen = nullptr; // Pincel para a cor verde
- ID2D1Factory: Cria objetos Direct2D e gerencia recursos.
- ID2D1HwndRenderTarget: Representa a superfície de renderização associada à janela.
- ID2D1SolidColorBrush: Permite desenhar formas com cores sólidas.
2. Função InitDirect2D para Inicialização do Direct2D
Esta função configura o ambiente Direct2D e cria o RenderTarget, essencial para desenhar na janela.
HRESULT InitDirect2D(HWND hWnd) {
HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &pFactory);
if (FAILED(hr)) return hr;
RECT rc;
GetClientRect(hWnd, &rc);
hr = pFactory->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hWnd, D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top)
),
&pRenderTarget
);
if (FAILED(hr)) return hr;
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Black), &pBrushBlack);
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Red), &pBrushRed);
pRenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Green), &pBrushGreen);
return S_OK;
}
- Criação da Fábrica ( pFactory ): Com D2D1CreateFactory, criamos uma instância da fábrica Direct2D.
- Target de Renderização: Criamos o HwndRenderTarget, uma superfície de renderização associada à janela ( hWnd ), usando as dimensões da área cliente da janela.
- Pincéis ( pBrushBlack, pBrushRed, pBrushGreen ): Criamos pincéis de cores para uso posterior na renderização de formas.
3. Função WndProc para o Procedimento de Janela
WndProc gerencia as mensagens enviadas para a janela e aciona o procedimento adequado para cada uma.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_PAINT:
Render();
ValidateRect(hWnd, NULL);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
- WM_PAINT: Quando a janela precisa ser redesenhada, chama a função Render.
- WM_DESTROY: Envia uma mensagem de encerramento ao sistema.
4. Função Render para Desenho dos Elementos 2D
A função Render usa o RenderTarget para desenhar um retângulo, um círculo e um triângulo verde usando uma geometria customizada.
void Render() {
pRenderTarget->BeginDraw();
pRenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::SkyBlue));
// Retângulo preto
pRenderTarget->FillRectangle(D2D1::RectF(50, 50, 150, 150), pBrushBlack);
// Círculo vermelho
pRenderTarget->FillEllipse(D2D1::Ellipse(D2D1::Point2F(300, 100), 50, 50), pBrushRed);
// Triângulo verde usando uma GeometrySink
ID2D1PathGeometry* pPathGeometry = nullptr;
pFactory->CreatePathGeometry(&pPathGeometry);
ID2D1GeometrySink* pSink = nullptr;
pPathGeometry->Open(&pSink);
pSink->BeginFigure(D2D1::Point2F(500, 50), D2D1_FIGURE_BEGIN_FILLED);
pSink->AddLine(D2D1::Point2F(450, 150));
pSink->AddLine(D2D1::Point2F(550, 150));
pSink->EndFigure(D2D1_FIGURE_END_CLOSED);
pSink->Close();
pRenderTarget->FillGeometry(pPathGeometry, pBrushGreen);
pPathGeometry->Release();
pSink->Release();
pRenderTarget->EndDraw();
}
Explicação do Código para o Triângulo Verde A criação do triângulo verde usa a função GeometrySink, que é uma interface do Direct2D para construir formas complexas:
- 1. Criação de uma PathGeometry: pFactory->CreatePathGeometry(&pPathGeometry); cria um objeto de geometria de caminho vazio, pPathGeometry, que será preenchido com os vértices do triângulo.
- 2. Abertura do GeometrySink: pPathGeometry->Open(&pSink); abre o GeometrySink, que é um canal para enviar dados sobre vértices ao Direct2D para criar formas personalizadas.
- 3. Desenho do Triângulo:
- Início da Figura: pSink->BeginFigure(D2D1::Point2F(500, 50), D2D1_FIGURE_BEGIN_FILLED); define o primeiro vértice do triângulo e indica que o triângulo deve ser preenchido.
- Adição de Linhas: pSink->AddLine(...) adiciona os dois vértices restantes.
- Finalização da Figura: pSink->EndFigure(D2D1_FIGURE_END_CLOSED); fecha a figura, conectando o último ponto ao ponto inicial para formar um triângulo.
- 4. Fechamento e Renderização:
- Fechamento do Sink: pSink->Close(); finaliza o envio de dados para o PathGeometry.
- Renderização: pRenderTarget->FillGeometry(pPathGeometry, pBrushGreen); preenche a forma com a cor verde.
O GeometrySink permite desenhar formas complexas ao especificar pontos e segmentos. Ao finalizar e fechar o sink, o Direct2D cria a geometria com base nas informações fornecidas.
5. Função Cleanup para Liberação de Recursos
A função Cleanup libera os recursos alocados, evitando vazamento de memória:
🚀 Resumo
void Cleanup() {
if (pRenderTarget) pRenderTarget->Release();
if (pBrushBlack) pBrushBlack->Release();
if (pBrushRed) pBrushRed->Release();
if (pBrushGreen) pBrushGreen->Release();
if (pFactory) pFactory->Release();
}
🚀 Resumo
Este código cria uma janela de renderização 2D usando Direct2D com diferentes formas ( retângulo, círculo e triângulo ). A função GeometrySink permite criar formas personalizadas como o triângulo, fornecendo mais controle sobre os vértices e a estrutura da figura.
0 Comentários