Inicio rápido de Direct2D

Direct2D es una API de modo inmediato y de código nativo para crear gráficos 2D. En este tema se muestra cómo usar Direct2D en una aplicación win32 típica para dibujar en un HWND.

Nota:

Si quieres crear una aplicación de Windows Store que usa Direct2D, consulta el tema inicio rápido de Direct2D para obtener Windows 8.

 

Este tema contiene las siguientes secciones:

Dibujar un rectángulo simple

Para dibujar un rectángulo mediante GDI, puede controlar el mensaje WM_PAINT , como se muestra en el código siguiente.

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. 

El código para dibujar el mismo rectángulo con Direct2D es similar: crea recursos de dibujo, describe una forma para dibujar, dibuja la forma y, a continuación, libera los recursos de dibujo. En las secciones siguientes se describe cada uno de estos pasos con detalle.

Paso 1: Incluir encabezado Direct2D

Además de los encabezados necesarios para una aplicación Win32, incluya el encabezado d2d1.h.

Paso 2: Crear un ID2D1Factory

Una de las primeras cosas que hace cualquier ejemplo de Direct2D es crear un ID2D1Factory.

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

La interfaz ID2D1Factory es el punto de partida para usar Direct2D; use id2D1Factory para crear recursos de Direct2D.

Al crear un generador, puede especificar si es multiproceso o de un solo subproceso. (Para obtener más información sobre las factorías multiproceso, vea los comentarios en la página de referencia ID2D1Factory). En este ejemplo se crea una fábrica de un solo subproceso.

En general, la aplicación debe crear el generador una vez y conservarlo durante la vida útil de la aplicación.

Paso 3: Crear un ID2D1HwndRenderTarget

Después de crear un generador, úselo para crear un destino de representación.



// 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
);

Un destino de representación es un dispositivo que puede realizar operaciones de dibujo y crear recursos de dibujo dependientes del dispositivo, como pinceles. Los diferentes tipos de destinos de representación se representan en diferentes dispositivos. En el ejemplo anterior se usa un ID2D1HwndRenderTarget, que se representa en una parte de la pantalla.

Cuando sea posible, un destino de representación usa la GPU para acelerar las operaciones de representación y crear recursos de dibujo. De lo contrario, el destino de representación usa la CPU para procesar las instrucciones de representación y crear recursos. (Puede modificar este comportamiento mediante las marcas de D2D1_RENDER_TARGET_TYPE al crear el destino de representación).

El método CreateHwndRenderTarget toma tres parámetros. El primer parámetro, una estructura de D2D1_RENDER_TARGET_PROPERTIES , especifica las opciones de visualización remota, si se fuerza el destino de representación para representarlo en el software o el hardware, y el PPP. El código de este ejemplo usa la función auxiliar D2D1::RenderTargetProperties para aceptar las propiedades de destino de representación predeterminadas.

El segundo parámetro, un D2D1_HWND_RENDER_TARGET_PROPERTIES estructura, especifica el HWND al que se representa el contenido, el tamaño inicial del destino de representación (en píxeles) y sus opciones de presentación. En este ejemplo se usa la función auxiliar D2D1::HwndRenderTargetProperties para especificar un HWND y un tamaño inicial. Usa opciones de presentación predeterminadas.

El tercer parámetro es la dirección del puntero que recibe la referencia de destino de representación.

Cuando se crea un destino de representación y la aceleración de hardware está disponible, se asignan recursos en la GPU del equipo. Al crear un destino de representación una vez y conservarlo siempre que sea posible, obtendrá ventajas de rendimiento. La aplicación debe crear destinos de representación una vez y retenerlos durante la vida útil de la aplicación o hasta que se reciba el error de D2DERR_RECREATE_TARGET . Cuando reciba este error, debe volver a crear el destino de representación (y los recursos que creó).

Paso 4: Crear un pincel

Al igual que una fábrica, un destino de representación puede crear recursos de dibujo. En este ejemplo, el destino de representación crea un pincel.

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

Un pincel es un objeto que pinta un área, como el trazo de una forma o el relleno de una geometría. El pincel de este ejemplo pinta un área con un color sólido predefinido, negro.

Direct2D también proporciona otros tipos de pinceles: pinceles degradados para pintar degradados lineales y radiales, y un pincel de mapa de bits para pintar con mapas de bits y patrones.

Algunas API de dibujo proporcionan lápices para dibujar contornos y pinceles para rellenar formas. Direct2D es diferente: no proporciona un objeto de lápiz, sino que usa un pincel para dibujar contornos y formas de relleno. Al dibujar esquemas, use la interfaz ID2D1StrokeStyle con un pincel para controlar las operaciones de pulsación de ruta de acceso.

Un pincel solo se puede usar con el destino de representación que lo creó y con otros destinos de representación en el mismo dominio de recursos. En general, debe crear pinceles una vez y conservarlos durante la vida útil del destino de representación que los creó. ID2D1SolidColorBrush es la excepción innecesaria; porque es relativamente económico crear, puede crear un ID2D1SolidColorBrush cada vez que dibuje un fotograma, sin que se produzca ningún impacto notable en el rendimiento. También puede usar un solo ID2D1SolidColorBrush y simplemente cambiar su color cada vez que lo use.

Paso 5: Dibujar el rectángulo

A continuación, use el destino de representación para dibujar el rectángulo.

 
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();  

El método DrawRectangle toma dos parámetros: el rectángulo que se va a dibujar y el pincel que se va a usar para pintar el contorno del rectángulo. Opcionalmente, también puede especificar el ancho del trazo, el patrón de guiones, la combinación de líneas y las opciones de límite final.

Debe llamar al método BeginDraw antes de emitir comandos de dibujo y debe llamar al método EndDraw una vez que haya terminado de emitir comandos de dibujo. El método EndDraw devuelve un HRESULT que indica si los comandos de dibujo se realizaron correctamente.

Paso 6: Liberar recursos

Cuando no haya más fotogramas para dibujar o cuando reciba el error de D2DERR_RECREATE_TARGET , libere el destino de representación y los dispositivos creados.

 
SafeRelease(pRT);
SafeRelease(pBlackBrush);

Cuando la aplicación haya terminado de usar recursos de Direct2D (por ejemplo, cuando esté a punto de salir), libere el generador de Direct2D.

 
SafeRelease(pD2DFactory);

Creación de una aplicación simple de Direct2D

El código de este tema muestra los elementos básicos de una aplicación Direct2D. Para mayor brevedad, el tema omite el marco de trabajo de la aplicación y el código de control de errores que es característica de una aplicación bien escrita. Para obtener un tutorial más detallado que muestre el código completo para crear una aplicación sencilla de Direct2D y muestre los procedimientos de diseño recomendados, consulte Creación de una aplicación direct2D sencilla.

Creación de una aplicación de Direct2D sencilla