Click here to Skip to main content
13,290,261 members (53,932 online)
Click here to Skip to main content
Add your own
alternative version


15 bookmarked
Posted 24 Sep 2010

Programming Direct2D – Part 2 – Basic Geometry

, 24 Sep 2010
Rate this:
Please Sign up or sign in to vote.
In this installment, let’s cover basic primitives. The basic primitives are the mostly used shapes like lines, rectangle, rounded rectangle, circle etc.

Few weeks ago, we covered the basics of Direct2D API and usage. In this instalment, let’s cover basic primitives. The basic primitives are the mostly used shapes like lines, rectangle, rounded rectangle, circle, etc. Direct2D can support more complex primitives (like path geometries) but let’s get introduced to basic primitives.

ID2D1Geometry class act as the base (interface) class for all geometry classes in Direct2D. The base class provides a minimum set interfaces to handle the data management and drawing operations. The derived classes like ID2D1RectangleGeometry, ID2D1RoundedRectangleGeometry and ID2D1EllipseGeometry, etc. provide the concrete implementation for each primitive. This is an absolutely object oriented concept which helps us to manage the code flexible and easy. The usage of interface classes is easy. To create the absolute parameters, several typesafe helper functions are available for creating rectangle, point values, etc. (same as RECT and POINT structure in Windows).


Here I demonstrate a sample program which can draw Rectangle, Rounded Rectangle and Ellipse n number of times in a multi document application.
The basic architecture remains the same.

  • The view class uses the Direct2DHandler class for Drawing using Direct2D.
  • The user interaction is handled in the view class and corresponding interfaces are called on user action or on window operations (like paint resize, etc.).
  • Since this is an MDI application, each view/tab contains the object of Direct2DHandler object.


Direct2DHandler Class

To support any number of primitives, the class contains a vector of IDirect2DGeometry pointers. Since this is an abstract class pointer, it can hold any primitive classes derived from it. Upon calling the draw function, the scene is cleared and each primitive will draw again in a loop.

UI Operation

This is a very basic application which allows us to draw something in a conventional way. The user can mark rectangle area using mouse and this will be passed to the interface for creating each primitive. The interfaces provided in the Direct2DHandler class will calculate the parameters from the given rectangle and create the geometry. The geometry will be inserted in the vector given as a member class. This application doesn’t support to delete the drawn primitives.

Creating Rectangle Geometry

void Direct2DHandler::CreateRectangle( LPCRECT pRect, bool bFill )
    D2D1_RECT_F rectangle = D2D1::Rect
	( pRect->left, pRect->top, pRect->right, pRect->bottom );

    ID2D1RectangleGeometry* pRectangle;
    m_pDirect2dFactory->CreateRectangleGeometry( rectangle, &pRectangle );
    m_Geometries.push_back( pRectangle );

Creating Ellipse Geometry

void Direct2DHandler::CreateEllipse( LPCRECT pRectBoundingBox )
    int halfX = ( pRectBoundingBox->right - pRectBoundingBox->left ) /2;
    int halfY = ( pRectBoundingBox->bottom - pRectBoundingBox->top ) /2;
    D2D1_ELLIPSE ellipse = D2D1::Ellipse( D2D1::Point2
      ( pRectBoundingBox->left + halfX, pRectBoundingBox->top + halfY), halfX, halfY );

    ID2D1EllipseGeometry* pEllipse;
    m_pDirect2dFactory->CreateEllipseGeometry( ellipse, &pEllipse );
    m_Geometries.push_back( pEllipse );

Create Rounded Rectangle Geometry

void Direct2DHandler::CreateRoundedRectangle
	(LPCRECT pRect, int radiusx, int radiusY, bool bFill )
    D2D1_ROUNDED_RECT rectangle = D2D1::RoundedRect( D2D1::Rect
	(pRect->left, pRect->top, pRect->right, pRect->bottom), radiusx, radiusY);
    ID2D1RoundedRectangleGeometry* pRRectangle;
    m_pDirect2dFactory->CreateRoundedRectangleGeometry( rectangle, &pRRectangle );
    m_Geometries.push_back( pRRectangle );

Primitives Container

Primitive container is declared as member of class:

std::vector<ID2D1Geometry*> m_Geometries;


HRESULT Direct2DHandler::OnRender()
    HRESULT hr = S_OK;

    hr = CreateDeviceResources();

    if (SUCCEEDED(hr))
        m_pRenderTarget->Clear( D2D1::ColorF(D2D1::ColorF::Black, 1.0f));
        // Iterate and draw all primitives
        for( std::vector<ID2D1Geometry*>::iterator it = m_Geometries.begin();
            it != m_Geometries.end(); ++it )
            m_pRenderTarget->DrawGeometry( *it, m_pLightSlateGrayBrush);

        hr = m_pRenderTarget->EndDraw();

        hr = S_OK;
    return hr;


Release all the allocated primitives during exit (destructor).

    for( std::vector<ID2D1Geometry*>::iterator it = m_Geometries.begin();
            it != m_Geometries.end(); ++it )




View Code

Initialize Direct2DHandler Object

int CDirect2DGeometrySampleView::OnCreate(LPCREATESTRUCT lpCreateStruct)
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	m_pRender = new Direct2DHandler( m_hWnd );

	return 0;

Delegate the Painting Operation to Direct2DHandler Class

// CDirect2DGeometrySampleView drawing
void CDirect2DGeometrySampleView::OnDraw(CDC* /*pDC*/)
    if( m_pRender )

Call Resize the Render Scene on Resizing the Window

void CDirect2DGeometrySampleView::OnSize(UINT nType, int cx, int cy)
    CView::OnSize(nType, cx, cy);

    if( m_pRender && cx && cy )
        m_pRender->OnResize( cx, cy );

Handle the menu commands to select the shape. The enumerations are locally defined.

void CDirect2DGeometrySampleView::OnShapeRrect()
	m_eShape = SHAPE_RRECT;

void CDirect2DGeometrySampleView::OnShapeRectangle()
	m_eShape = SHAPE_RECT;

void CDirect2DGeometrySampleView::OnShapeEllipse()
	m_eShape = SHAPE_ELLIPSE;

Call the Handler Interface to Create Geometry on Mouse Operation

void CDirect2DGeometrySampleView::OnLButtonUp(UINT nFlags, CPoint point)
	m_ptEnd = point;

	if( SHAPE_RECT == m_eShape )
		m_pRender->CreateRectangle( CRect( m_ptBeg, point ), true );
	else if( SHAPE_RRECT == m_eShape )
			( CRect( m_ptBeg, point),10,10, true );
	else if( SHAPE_ELLIPSE == m_eShape )
		m_pRender->CreateEllipse( CRect( m_ptBeg, point ));


The code is self explaining to understand the operations. However, please find the full project source code here (GitHub).


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Sarath C
Technical Lead
India India
Software Developer

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
Thornik1-May-13 14:23
memberThornik1-May-13 14:23 
GeneralMy vote of 2 Pin
S.H.Bouwhuis30-Sep-10 1:58
memberS.H.Bouwhuis30-Sep-10 1:58 
GeneralRe: My vote of 2 Pin
Sarath.9-Oct-10 17:15
memberSarath.9-Oct-10 17:15 
GeneralRe: My vote of 4 Pin
S.H.Bouwhuis10-Oct-10 21:53
memberS.H.Bouwhuis10-Oct-10 21:53 
GeneralRe: My vote of 4 Pin
Sarath.11-Oct-10 21:05
memberSarath.11-Oct-10 21:05 
GeneralRe: My vote of 4 Pin
S.H.Bouwhuis11-Oct-10 21:58
memberS.H.Bouwhuis11-Oct-10 21:58 
GeneralRe: My vote of 4 Pin
Sarath.11-Oct-10 22:11
memberSarath.11-Oct-10 22:11 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171207.1 | Last Updated 25 Sep 2010
Article Copyright 2010 by Sarath C
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid