Direct2D-Schnellstart für Windows 8
Direct2D ist eine API mit nativem Code im Direktmodus zum Erstellen von 2D-Grafiken. In diesem Thema wird veranschaulicht, wie Direct2D zum Zeichnen in eine Windows::UI::Core::CoreWindow verwendet wird.
Dieses Thema enthält folgende Abschnitte:
- Zeichnen eines einfachen Rechtecks
- Schritt 1: Direct2D-Header hinzufügen
- Schritt 2: Erstellen einer ID2D1Factory1
- Schritt 3: Erstellen einer ID2D1Device und eines ID2D1DeviceContext
- Schritt 4: Erstellen eines Pinsels
- Schritt 5: Zeichnen des Rechtecks
- Beispielcode
Zeichnen eines einfachen Rechtecks
Um ein Rechteck mithilfe von GDI zuzeichnen, 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 desselben 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: Direct2D-Header hinzufügen
Schließen Sie zusätzlich zu den für die Anwendung erforderlichen Headern die Header d2d1.h und d2d1 _ 1.h ein.
Schritt 2: Erstellen einer ID2D1Factory1
Eines der ersten Dinge, die ein Direct2D-Beispiel tut, 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 eine Multithread- oder Singlethread-Factory handelt. (Weitere Informationen zu Multithreadfactorys finden Sie in den Anmerkungen auf der Referenzseite zu ID2D1Factory.) 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 einer ID2D1Device und eines ID2D1DeviceContext
Nachdem Sie eine Factory erstellt haben, verwenden Sie sie, um ein Direct2D-Gerät zu erstellen, und verwenden Sie dann das Gerät, um einen Direct2D-Gerätekontext zu erstellen. Um diese Direct2D-Objekte zu erstellen, müssen Sie über ein Direct3D 11-Gerät, ein DXGI-Gerätund eine DXGI-Austauschkette 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 und als Renderziel zu verwenden. Der Gerätekontext kann auf verschiedene Arten von Zielen gerendert werden.
Der Code hier deklariert die Eigenschaften für bitmap, die mit einer DXGI-Swapkette verknüpft sind, die zu 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 der Oberfläche der Swapkette gerendert.
Sobald Sie über die Direct2D-Oberfläche verfügen, verwenden Sie die ID2D1DeviceContext::SetTarget-Methode, um sie als aktives Renderziel festlegen.
// 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 Arten von Pinseln: Farbverlaufspinsel zum Malen von linearen und radialen Farbverläufen, ein Bitmappinsel zum Malen mit Bitmaps und Mustern und ab Windows 8 ein Bildpinsel zum Malen mit einem gerenderten Bild.
Einige Zeichnungs-APIs stellen Stifte zum Zeichnen von Konturen und Pinseln zum Füllen von Formen zur Verfügung. Direct2D ist anders: Es stellt kein Stiftobjekt zur Verfügung, sondern verwendet einen Pinsel zum Zeichnen von Konturen und Füllen von Formen. Verwenden Sie beim Zeichnen von Konturen die ID2D1StrokeStyle-Schnittstelle, oder beginnen Sie Windows 8 der ID2D1StrokeStyle1-Schnittstelle mit einem Pinsel, um Pfadknittingvorgänge zu steuern.
Ein Pinsel kann nur mit dem Renderziel, das ihn erstellt hat, und mit anderen Renderzielen in derselben Ressourcendomäne verwendet werden. Im Allgemeinen sollten Sie Pinsel einmal erstellen und für die Lebensdauer des Renderziels beibehalten, mit 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 eine spürbare Leistungssteigerung auftritt. Sie können auch einen einzelnen ID2D1SolidColorBrush verwenden und bei jeder Verwendung einfach seine Farbe oder Deckkraft ä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, ¶meters);
);
Die DrawRectangle-Methode verwendet zwei Parameter: das zu zeichnende Rechteck und den Pinsel, der zum Zeichnen der Kontur des Rechtecks verwendet werden soll. Optional können Sie auch die Optionen Strichbreite, Bindestrichmuster, Linienverkn seitlich und Endende angeben.
Sie müssen die BeginDraw-Methode aufrufen, bevor Sie Zeichnungsbefehle ausführen, und Sie müssen die EndDraw-Methode aufrufen, nachdem Sie das Ausstellen von Zeichnungsbefehlen abgeschlossen haben. Die EndDraw-Methode gibt ein HRESULT zurück, das angibt, ob die Zeichnungsbefehle erfolgreich waren. Wenn dies nicht erfolgreich ist, löst die ThrowIfFailed-Hilfsfunktion eine Ausnahme aus.
Die IDXGISwapChain::P resent-Methode tauscht die Pufferoberfläche mit der auf der Bildschirmoberfläche aus, um das Ergebnis anzuzeigen.
Beispielcode
Der Code in diesem Thema zeigt die grundlegenden Elemente einer Direct2D-Anwendung. Zur Kürze werden im Thema das Anwendungsframework und der Fehlerbehandlungscode ausgelassen, der für eine gut geschriebene Anwendung eigenschaft ist.