Condividi tramite


Guida introduttiva a Direct2D

Direct2D è un'API in modalità immediata e nativa per la creazione di grafica 2D. Questo argomento illustra come usare Direct2D internamente a un'applicazione tipica Win32 per disegnare su un HWND.

Nota

Se vuoi creare un'app di Windows Store che usa Direct2D, vedi l'argomento di avvio rapido Direct2D per Windows 8.

 

Questo argomento contiene le sezioni seguenti:

Disegno di un rettangolo semplice

Per disegnare un rettangolo usando GDI, è possibile gestire il messaggio WM_PAINT, come illustrato nel codice seguente.

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. 

Il codice per disegnare lo stesso rettangolo con Direct2D è simile: crea risorse di disegno, descrive una forma da disegnare, disegna la forma, quindi rilascia le risorse di disegno. Le sezioni seguenti descrivono in dettaglio ognuno di questi passaggi.

Passaggio 1: Includere l'intestazione Direct2D

Oltre alle intestazioni necessarie per un'applicazione Win32, includere l'intestazione d2d1.h.

Passaggio 2: Creare un ID2D1Factory

Una delle prime operazioni eseguite da qualsiasi esempio Direct2D è la creazione di un ID2D1Factory.

ID2D1Factory* pD2DFactory = NULL;
HRESULT hr = D2D1CreateFactory(
    D2D1_FACTORY_TYPE_SINGLE_THREADED,
    &pD2DFactory
    );

L'interfacciaID2D1Factoryè il punto di partenza per l'uso di Direct2D; usare un ID2D1Factory per creare risorse Direct2D.

Quando si crea una factory, è possibile specificare se è multithread o a singolo thread. Per altre informazioni sulle factory multithreading, vedere le osservazioni nella pagina di riferimento ID2D1Factory. In questo esempio viene creata una factory a thread singolo.

In generale, l'applicazione dovrebbe creare la fabbrica una sola volta e conservarla per l'intera durata dell'applicazione.

Passaggio 3: Creare un ID2D1HwndRenderTarget

Dopo aver creato una fabbrica, usarla per creare un target di rendering.



// Obtain the size of the drawing area.
RECT rc;
GetClientRect(hwnd, &rc);

// Create a Direct2D render target          
ID2D1HwndRenderTarget* pRT = NULL;          
HRESULT hr = pD2DFactory->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties(),
    D2D1::HwndRenderTargetProperties(
        hwnd,
        D2D1::SizeU(
            rc.right - rc.left,
            rc.bottom - rc.top)
    ),
    &pRT
);

Una destinazione di rendering è un dispositivo che può eseguire operazioni di disegno e creare risorse di disegno dipendenti dal dispositivo, ad esempio pennelli. Tipi diversi di obiettivi di rendering vengono visualizzati su dispositivi diversi. L'esempio precedente usa un ID2D1HwndRenderTarget, che esegue il rendering in una parte dello schermo.

Quando possibile, una destinazione di rendering usa la GPU per accelerare le operazioni di rendering e creare risorse di disegno. In caso contrario, la destinazione di rendering usa la CPU per elaborare le istruzioni di rendering e creare risorse. È possibile modificare questo comportamento usando i flag D2D1_RENDER_TARGET_TYPE quando si crea la destinazione di rendering.

Il metodoCreateHwndRenderTargetaccetta tre parametri. Il primo parametro, una struct D2D1_RENDER_TARGET_PROPERTIES, specifica le opzioni di visualizzazione remota, se forzare il target di rendering su software o hardware e il DPI. Il codice in questo esempio usa la funzione helper D2D1::RenderTargetProperties per accettare le proprietà di destinazione di rendering predefinite.

Il secondo parametro, uno struct D2D1_HWND_RENDER_TARGET_PROPERTIES, specifica il HWND a cui viene eseguito il rendering del contenuto, le dimensioni iniziali della destinazione di rendering (in pixel) e le relative opzioni di presentazione . Questo esempio usa la funzione helper D2D1::HwndRenderTargetProperties per specificare un HWND e le dimensioni iniziali. Usa le opzioni di presentazione predefinite.

Il terzo parametro è l'indirizzo del puntatore che riceve il riferimento del target di rendering.

Quando si crea una destinazione di rendering e l'accelerazione hardware è disponibile, si allocano le risorse sulla GPU del computer. Creando una destinazione di rendering una sola volta e mantenendola il più a lungo possibile, si ottengono vantaggi in termini di prestazioni. L'applicazione deve creare destinazioni di rendering una sola volta e mantenerle per la durata dell'applicazione o fino a quando non viene ricevuto l'errore D2DERR_RECREATE_TARGET. Quando si verifica questo errore, dovrai ricreare il target di rendering e qualsiasi risorsa ad esso associata.

Passaggio 4: Creare un pennello

Come una fabbrica, una destinazione di rendering può creare risorse di disegno. In questo esempio, la destinazione di rendering crea un pennello.

ID2D1SolidColorBrush* pBlackBrush = NULL;
if (SUCCEEDED(hr))
{
            
    pRT->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        ); 
}

Un pennello è un oggetto che disegna un'area, ad esempio il tratto di una forma o il riempimento di una geometria. Il pennello in questo esempio disegna un'area con un colore a tinta unita predefinito, nero.

Direct2D fornisce anche altri tipi di pennelli: pennelli a sfumatura per dipingere sfumature lineari e radiali e un pennello bitmap per dipingere con bitmap e pattern.

Alcune API di disegno forniscono penne per disegnare contorni e pennelli per riempire le forme. Direct2D è diverso: non fornisce un oggetto penna, ma usa un pennello per disegnare contorni e riempire le forme. Quando si disegnano contorni, utilizzare l'interfaccia ID2D1StrokeStyle con un pennello per controllare le operazioni di tracciatura del percorso.

Un pennello può essere usato solo con la destinazione di rendering che l'ha creata e con altre destinazioni di rendering nello stesso dominio di risorse. In generale, è necessario creare i pennelli una sola volta e conservarli per l'intera durata della destinazione di rendering che li ha creati. ID2D1SolidColorBrush è l'unica eccezione; poiché ha un costo di creazione relativamente basso, è possibile creare un ID2D1SolidColorBrush ogni volta che si disegna un fotogramma, senza alcun impatto significativo sulle prestazioni. È anche possibile usare un singolo ID2D1SolidColorBrush e modificarne il colore ogni volta che lo usi.

Passaggio 5: Disegnare il rettangolo

Successivamente, utilizzare l'obiettivo di rendering per disegnare il rettangolo.

 
pRT->BeginDraw();

pRT->DrawRectangle(
    D2D1::RectF(
        rc.left + 100.0f,
        rc.top + 100.0f,
        rc.right - 100.0f,
        rc.bottom - 100.0f),
        pBlackBrush);

HRESULT hr = pRT->EndDraw();  

Il metodo DrawRectangle accetta due parametri: il rettangolo da disegnare e il pennello da utilizzare per disegnare il contorno del rettangolo. Facoltativamente, è anche possibile specificare la larghezza del tratto, il motivo a tratteggio, la giunzione di linea e le opzioni di terminale.

È necessario chiamare il metodo BeginDraw prima di eseguire comandi di disegno ed è necessario chiamare il metodo EndDraw dopo aver completato l'esecuzione dei comandi di disegno. Il metodo EndDraw restituisce un HRESULT che indica se i comandi di disegno hanno avuto esito positivo.

Passaggio 6: Rilasciare le risorse

Quando non ci sono più fotogrammi da disegnare o quando si verifica l'errore D2DERR_RECREATE_TARGET, rilascia il target di rendering e tutti i dispositivi creati.

 
SafeRelease(pRT);
SafeRelease(pBlackBrush);

Quando la tua applicazione ha terminato l'uso delle risorse Direct2D, ad esempio quando sta per uscire, rilascia la Factory Direct2D.

 
SafeRelease(pD2DFactory);

Creare un'applicazione Direct2D semplice

Il codice in questo argomento illustra gli elementi di base di un'applicazione Direct2D. Per brevità, l'argomento omette il framework dell'applicazione e il codice di gestione degli errori caratteristica di un'applicazione ben scritta. Per una procedura più dettagliata che illustra il codice completo per la creazione di una semplice applicazione Direct2D e le migliori pratiche di progettazione, consultare la sezione Creare una semplice applicazione Direct2D.

Creare una semplice applicazione Direct2D