Direct2D quick start Start a Direct2D program in a standard win32 application

To use Direct2D, first you need to include “d2d.h” and link “d2d.lib”.

The most important object for Direct2D is ID2D1Factory and ID2D1HwndRenderTarget. In most case you create and keep both of them until the end of the application or retrieve error D2DERR_RECREATE_TARGET from ID2D1HwndRenderTarget::EndDraw.

To create the direct2d factory and target, we need window’s handle, hwnd.

HRESULT hret;
RECT crect;
ID2D1Factory* d2d1_factory_;
ID2D1HwndRenderTarget* d2d1_target_;

// hwnd is the application window handle
GetClientRect(hwnd, &crect);

hret = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2d1_factory_);
hret = d2d1_factory_->CreateHwndRenderTarget(
    D2D1::RenderTargetProperties(),
    D2D1::HwndRenderTargetProperties(hwnd,
        D2D1::SizeU(
            crect.right - crect.left,
            crect.bottom - crect.top)
    ),
    &d2d1_target_);

The actual “drawing” logic should be inside the WM_PAINT message in the win32 standard application.

case WM_PAINT:
{
    // make sure the d2d target is initialized here 
    PAINTSTRUCT ps;
    HRESULT hret;
    HDC hdc = BeginPaint(hWnd, &ps);

    // start direct2d drawing    
    d2d1_target_->BeginDraw();
    
    // change the orientation to default
    d2d1_target_->SetTransform(D2D1::Matrix3x2F::Identity());
    
    // set the background color
    d2d1_target_->Clear(D2D1::ColorF(D2D1::ColorF::AliceBlue));
    
    // end of direct2d drawing
    hret = d2d1_target_->EndDraw();
    
    if (hret == D2DERR_RECREATE_TARGET)
    {
        // release the resource
        d2d1_target_->Release();
        d2d1_factory_->Release();
        
        // re-create direct2d factory and target here
    }
    
    EndPaint(hWnd, &ps);
}
break;

When the window change its size due to any reason, we have to call Resize.

case WM_SIZE:
{
    // wParam could be SIZE_RESTORED, SIZE_MINIMIZED,
    // SIZE_MAXSHOW, SIZE_MAXIMIZED, SIZE_MAXHIDE
    // but direct2d could handle size of 0 so just call Resize(SizeU)
    UINT width = LOWORD(lParam);
    UINT height = HIWORD(lParam);
    d2d1_target_->Resize(D2D1::SizeU(w, h));
}
break;

That’s all. Easy peasy. 🙂