Direct2D-Schnellstart für Windows 8

Direct2D ist eine API für nativen Code im unmittelbaren Modus zum Erstellen von 2D-Grafiken. In diesem Thema wird veranschaulicht, wie Sie Direct2D verwenden, um ein Windows::UI::Core::CoreWindow zu zeichnen.

Dieses Thema enthält folgende Abschnitte:

Zeichnen eines einfachen Rechtecks

Um ein Rechteck mit GDI zu zeichnen, können Sie die WM_PAINT-Nachricht behandeln, wie im folgenden Code gezeigt.

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. 

Der Code zum Zeichnen des gleichen Rechtecks mit Direct2D ist ähnlich: Er erstellt Zeichnungsressourcen, beschreibt eine zu zeichnende Form, zeichnet die Form und gibt dann die Zeichnungsressourcen frei. In den folgenden Abschnitten werden die einzelnen Schritte ausführlich beschrieben.

Schritt 1: Einschließen des Direct2D-Headers

Zusätzlich zu den für die Anwendung erforderlichen Headern enthalten Sie die Header d2d1.h und d2d1_1.h.

Schritt 2: Erstellen einer ID2D1Factory1

Eines der ersten Schritte eines Direct2D-Beispiels ist das Erstellen einer ID2D1Factory1.

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

Die ID2D1Factory1-Schnittstelle ist der Ausgangspunkt für die Verwendung von Direct2D. verwenden Sie eine ID2D1Factory1 , um Direct2D-Ressourcen zu erstellen.

Wenn Sie eine Factory erstellen, können Sie angeben, ob es sich um multi- oder Singlethreads handelt. (Weitere Informationen zu Multithreadfabriken finden Sie in den Anmerkungen auf der ID2D1Factory-Referenzseite.) In diesem Beispiel wird eine Singlethread-Factory erstellt.

Im Allgemeinen sollte Ihre Anwendung die Factory einmal erstellen und für die Lebensdauer der Anwendung beibehalten.

Schritt 3: Erstellen eines ID2D1Device und eines ID2D1DeviceContext

Nachdem Sie eine Factory erstellt haben, können Sie damit ein Direct2D-Gerät erstellen und dann mit dem Gerät einen Direct2D-Gerätekontext erstellen. Zum Erstellen dieser Direct2D-Objekte müssen Sie über ein Direct3D 11-Gerät , ein DXGI-Gerät und eine DXGI-Swapchain verfügen. Informationen zum Erstellen der erforderlichen Voraussetzungen finden Sie unter Geräte und Gerätekontexte .


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

Ein Gerätekontext ist ein Gerät, das Zeichnungsvorgänge ausführen und geräteabhängige Zeichnungsressourcen wie Pinsel erstellen kann. Sie verwenden auch den Gerätekontext, um eine ID2D1Bitmap mit einer DXGI-Oberfläche zu verknüpfen, die als Renderziel verwendet werden soll. Der Gerätekontext kann in verschiedenen Zieltypen gerendert werden.

Der code hier deklariert die Eigenschaften für Bitmaps, die mit einer DXGI-Swapkette verknüpft sind, die mit einem CoreWindow gerendert wird. Die ID2D1DeviceContext::CreateBitmapFromDxgiSurface-Methode ruft eine Direct2D-Oberfläche von der DXGI-Oberfläche ab. Dadurch wird alles, was in der Ziel-ID2D1Bitmap gerendert wird, auf die Oberfläche der Swapchain gerendert.

Sobald Sie über die Direct2D-Oberfläche verfügen, verwenden Sie die ID2D1DeviceContext::SetTarget-Methode , um sie als aktives Renderziel festzulegen.

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

Schritt 4: Erstellen eines Pinsels

Wie eine Factory kann ein Gerätekontext Zeichnungsressourcen erstellen. In diesem Beispiel erstellt der Gerätekontext einen Pinsel.

ComPtr<ID2D1SolidColorBrush> pBlackBrush;
DX::ThrowIfFailed(
   m_d2dContext->CreateSolidColorBrush(
        D2D1::ColorF(D2D1::ColorF::Black),
        &pBlackBrush
        )
);

Ein Pinsel ist ein Objekt, das einen Bereich zeichnet, z. B. den Strich einer Form oder die Füllung einer Geometrie. Der Pinsel in diesem Beispiel zeichnet einen Bereich mit einer vordefinierten Volltonfarbe schwarz.

Direct2D bietet auch andere Pinseltypen: Farbverlaufspinsel zum Zeichnen linearer und radialer Farbverläufe, einen Bitmappinsel zum Malen mit Bitmaps und Mustern und ab Windows 8 einen Bildpinsel zum Malen mit einem gerenderten Bild.

Einige Zeichnungs-APIs bieten Stifte zum Zeichnen von Konturen und Pinsel zum Füllen von Formen. Direct2D ist anders: Es stellt kein Stiftobjekt bereit, sondern verwendet einen Pinsel zum Zeichnen von Konturen und Füllen von Formen. Verwenden Sie beim Zeichnen von Gliederungen die ID2D1StrokeStyle-Schnittstelle oder ab Windows 8 der ID2D1StrokeStyle1-Schnittstelle mit einem Pinsel, um Pfadstreichvorgänge zu steuern.

Ein Pinsel kann nur mit dem Renderziel verwendet werden, von dem er erstellt wurde, und mit anderen Renderzielen in derselben Ressourcendomäne. Im Allgemeinen sollten Sie Pinsel einmal erstellen und sie für die Lebensdauer des Renderziels beibehalten, von dem sie erstellt wurden. ID2D1SolidColorBrush ist die einzige Ausnahme. da die Erstellung relativ kostengünstig ist, können Sie jedes Mal, wenn Sie einen Frame zeichnen, einen ID2D1SolidColorBrush erstellen, ohne dass die Leistung spürbar ist. Sie können auch einen einzelnen ID2D1SolidColorBrush verwenden und einfach seine Farbe oder Deckkraft bei jeder Verwendung ändern.

Schritt 5: Zeichnen des Rechtecks

Verwenden Sie als Nächstes den Gerätekontext, um das Rechteck zu zeichnen.

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

Die DrawRectangle-Methode benötigt zwei Parameter: das zu zeichnende Rechteck und den Pinsel, der zum Zeichnen des Umrisses des Rechtecks verwendet werden soll. Optional können Sie auch die Optionen Strichbreite, Bindestrichmuster, Linienverknappung und Endkappe angeben.

Sie müssen die BeginDraw-Methode aufrufen, bevor Sie Zeichnungsbefehle ausgeben, und Sie müssen die EndDraw-Methode aufrufen, nachdem Sie die Zeichenbefehle ausgegeben haben. Die EndDraw-Methode gibt ein HRESULT zurück, das angibt, ob die Zeichnungsbefehle erfolgreich waren. Wenn dies nicht erfolgreich ist, löst die Hilfsfunktion ThrowIfFailed eine Ausnahme aus.

Mit der IDXGISwapChain::P resent-Methode wird die Pufferoberfläche durch die Bildschirmoberfläche auf dem Bildschirm ausgetauscht, um das Ergebnis anzuzeigen.

Beispielcode

Der Code in diesem Thema zeigt die grundlegenden Elemente einer Direct2D-Anwendung. Aus Gründen der Kürze werden im Thema das Anwendungsframework und der Fehlerbehandlungscode weggelassen, der für eine gut geschriebene Anwendung charakteristisch ist.