Compartir a través de


Inicio rápido de Direct2D para Windows 8

Direct2D es una API en modo inmediato de código nativo para crear gráficos 2D. En este tema se muestra cómo usar Direct2D para dibujar en windows ::UI::Core::CoreWindow.

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 en detalle.

Paso 1: Incluir encabezado direct2D

Además de los encabezados necesarios para la aplicación, incluya los encabezados d2d1.h y d2d1_1.h.

Paso 2: Crear un ID2D1Factory1

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

DX::ThrowIfFailed(
        D2D1CreateFactory(
            D2D1_FACTORY_TYPE_SINGLE_THREADED,
            __uuidof(ID2D1Factory1),
            &options,
            &m_d2dFactory
            )
        );

La interfaz ID2D1Factory1 es el punto de partida para usar Direct2D; usa un ID2D1Factory1 para crear recursos de Direct2D.

Al crear una fábrica, puede especificar si es multiproceso o de un solo subproceso. (Para obtener más información sobre las factorías multiproceso, vea los comentarios de 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 ID2D1Device y un ID2D1DeviceContext

Después de crear un generador, úselo para crear un dispositivo Direct2D y, a continuación, use el dispositivo para crear un contexto de dispositivo Direct2D. Para crear estos objetos Direct2D, debes tener un dispositivo Direct3D 11 , un dispositivo DXGI y una cadena de intercambio DXGI. Consulta Dispositivos y contextos de dispositivo para obtener información sobre cómo crear los requisitos previos necesarios.


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

Un contexto de dispositivo es un dispositivo que puede realizar operaciones de dibujo y crear recursos de dibujo dependientes del dispositivo, como pinceles. También usas el contexto del dispositivo para vincular id2D1Bitmap a una superficie DXGI para usarla como destino de representación. El contexto del dispositivo se puede representar en diferentes tipos de destinos.

El código aquí declara las propiedades del mapa de bits que se vinculan a una cadena de intercambio DXGI que se representa en coreWindow. El método ID2D1DeviceContext::CreateBitmapFromDxgiSurface obtiene una superficie Direct2D de la superficie DXGI. Esto hace que todo lo que se represente en el id. de destino ID2D1Bitmap se representa en la superficie de la cadena de intercambio.

Una vez que tengas la superficie direct2D, usa el método ID2D1DeviceContext::SetTarget para establecerlo como destino de representación activo.

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

Paso 4: Crear un pincel

Al igual que un generador, un contexto de dispositivo puede crear recursos de dibujo. En este ejemplo, el contexto del dispositivo crea un pincel.

ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
   m_d2dContext->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, un pincel de mapa de bits para pintar con mapas de bits y patrones, y a partir de Windows 8, un pincel de imagen para pintar con una imagen representada.

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, pero usa un pincel para dibujar contornos y formas de relleno. Al dibujar contornos, use la interfaz ID2D1StrokeStyle o a partir de Windows 8 la interfaz ID2D1StrokeStyle1, 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 del destino de representación que los creó. ID2D1SolidColorBrush es la excepción innecesaria; dado que 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 o opacidad cada vez que lo use.

Paso 5: Dibujar el rectángulo

A continuación, use el contexto del dispositivo para dibujar el rectá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, &parameters);
);

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 extremo final.

Debe llamar al método BeginDraw antes de emitir cualquier comando de dibujo y debe llamar al método EndDraw después de haber terminado de emitir comandos de dibujo. El método EndDraw devuelve un VALOR HRESULT que indica si los comandos de dibujo se realizaron correctamente. Si no se realiza correctamente, la función auxiliar ThrowIfFailed producirá una excepción.

El método IDXGISwapChain::P resent intercambia la superficie del búfer con la superficie en pantalla para mostrar el resultado.

Ejemplo de código

El código de este tema muestra los elementos básicos de una aplicación Direct2D. Por motivos de 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.