適用于 Windows 8 的 Direct2D 快速入門

Direct2D 是用來建立 2D 圖形的原生程式碼立即模式 API。 本主題說明如何使用 Direct2D 繪製至 Windows::UI::Core::CoreWindow

本主題包含下列幾節:

繪製簡單矩形

若要使用 GDI繪製矩形,您可以處理 WM_PAINT 訊息,如下列程式碼所示。

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. 

使用 Direct2D 繪製相同矩形的程式碼類似:它會建立繪圖資源、描述要繪製的圖形、繪製圖形,然後釋放繪圖資源。 後續各節會詳細說明每個步驟。

步驟 1:包含 Direct2D 標頭

除了應用程式所需的標頭之外,還包含 d2d1.h 和 d2d1_1.h 標頭。

步驟 2:建立 ID2D1Factory1

任何 Direct2D 範例所執行的第一件事之一,就是建立 ID2D1Factory1

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

ID2D1Factory1介面是使用 Direct2D 的起點;使用ID2D1Factory1建立 Direct2D 資源。

當您建立處理站時,可以指定它是多執行緒還是單一執行緒。 (如需多執行緒處理站的詳細資訊,請參閱 ID2D1Factory 參考頁面上的備註。) 此範例會建立單一執行緒處理站。

一般而言,您的應用程式應該建立處理站一次,並在應用程式存留期間保留它。

步驟 3:建立 ID2D1Device 和 ID2D1DeviceCoNtext

建立處理站之後,請使用它來建立 Direct2D 裝置,然後使用裝置建立 Direct2D 裝置內容。 若要建立這些 Direct2D 物件,您必須擁有 Direct3D 11 裝置DXGI 裝置DXGI 交換鏈結。 如需建立必要條件的詳細資訊,請參閱 裝置和裝置內容


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

裝置內容是可以執行繪圖作業並建立裝置相依繪圖資源的裝置,例如筆刷。 您也可以使用裝置內容將 ID2D1Bitmap 連結到 DXGI 表面,以作為轉譯目標使用。 裝置內容可以轉譯為不同類型的目標。

此處的程式碼會宣告點陣圖的屬性,該點陣圖會連結至轉譯至 CoreWindow的 DXGI 交換鏈結。 ID2D1DeviceCoNtext::CreateBitmapFromDxgiSurface方法會從 DXGI 表面取得 Direct2D 表面。 如此一來,任何轉譯至目標 ID2D1Bitmap 的任何專案就會轉譯為交換鏈結的介面。

擁有 Direct2D 表面之後,請使用 ID2D1DeviceCoNtext::SetTarget 方法將其設定為作用中的轉譯目標。

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

步驟 4:建立筆刷

就像處理站一樣,裝置內容可以建立繪圖資源。 在此範例中,裝置內容會建立筆刷。

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

筆刷是繪製區域的物件,例如圖形的筆劃或幾何填滿。 本範例中的筆刷會使用預先定義的純色黑色繪製區域。

Direct2D 也提供其他類型的筆刷:用於繪製線性和星形漸層的漸層筆刷、使用點陣圖和圖樣繪製的點陣圖筆刷,以及從Windows 8開始,使用轉譯影像繪製的影像筆刷

某些繪圖 API 提供畫筆來繪製外框和筆刷以填滿圖形。 Direct2D 不同:它不提供畫筆物件,而是使用筆刷繪製外框和填滿圖形。 繪製外框時,請使用ID2D1StrokeStyle介面,或從ID2D1StrokeStyle1介面Windows 8開始,並搭配筆刷來控制路徑結構作業。

筆刷只能與建立它的轉譯目標以及相同資源網域中的其他轉譯目標搭配使用。 一般而言,您應該建立筆刷一次,並在建立筆刷的轉譯目標存留期間保留筆刷。 ID2D1SolidColorBrush 是單一例外狀況;因為建立相當便宜,所以每次繪製框架時,您都可以建立 ID2D1SolidColorBrush ,而不會達到任何明顯的效能。 您也可以使用單一 ID2D1SolidColorBrush ,只要每次使用它時變更其色彩或不透明度即可。

步驟 5:繪製矩形

接下來,使用裝置內容繪製矩形。

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

DrawRectangle方法會採用兩個參數:要繪製的矩形,以及用來繪製矩形外框的筆刷。 您也可以選擇性地指定筆劃寬度、虛線圖樣、線條聯結和結束端點選項。

您必須在發出任何繪圖命令之前呼叫 BeginDraw 方法,而且必須在完成發出繪圖命令之後呼叫 EndDraw 方法。 EndDraw方法會傳回HRESULT,指出繪圖命令是否成功。 如果失敗,ThrowIfFailed 協助程式函式將會擲回例外狀況。

IDXGISwapChain::P resent方法會將緩衝區表面與螢幕上的 交換,以顯示結果。

程式碼範例

本主題中的程式碼會顯示 Direct2D 應用程式的基本元素。 為了簡潔起見,本主題會省略應用程式架構和錯誤處理常式代碼,這是撰寫良好應用程式的特性。