65.9K
CodeProject is changing. Read more.
Home

Dynamic DC

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.44/5 (5 votes)

Sep 19, 2000

CPOL
viewsIcon

88366

A Device Context class to draw on a window outside of a WM_PAINT handler

Introduction

CDynamicDC is a very small class that provides an easy and robust method for drawing on a window outside of the WM_PAINT handler. The entire implementation of the class is inline because no member function is more than two lines of executable code!

Why?

The class is so small that at first glance, one may ask why it is useful. The key advantages that the class provide are:

  1. Ease of use. Simply instantiate the object with a window handle and use it as a DC
  2. Guaranteed and Automatic release of system DC resource.
  3. The DC resource is freed in the destructor, so instantiate the object on the stack and the resource will always be freed even if an exception if generated
  4. Automatic type conversions. An instance of this class can be passed as a parameter to any function that is expecting HDC, CDC* or CDC& parameter types

Examples

Using the Device Context as a Win32 HDC.

CDynamicDC dc(hWnd);
::MoveTo(dc, 10, 10, &ptOld);
::LineTo(dc, 100, 100);

Using the Device Context as a pointer to an MFC CDC class.

CDynamicDC dc(hWnd);
dc->MoveTo(10, 10);
dc->LineTo(100, 100);

Using the Device Context as a reference to an MFC CDC class.

CDynamicDC dcDynamic(hWnd);
CDC &dc(*dcDynamic);
dc.MoveTo(10, 10);
dc.LineTo(100, 100);

The Code

class CDynamicDC
{
  private:
    HDC  m_hDC;
    HWND m_hWnd;

  public:
    CDynamicDC(CWnd *__pWnd);
    CDynamicDC(HWND __hWnd);
    virtual ~CDynamicDC();

    operator HDC();     // dynamic conversion to HDC
    CDC *operator->();  // dynamic conversion to CDC pointer
    operator CDC*();    // allow CDC pointer dereferencing
};

// constructor initialised with an MFC CWnd pointer
inline CDynamicDC::CDynamicDC(CWnd *__pWnd)
  : m_hDC(NULL),
    m_hWnd(NULL)
{
    ASSERT(__pWnd != NULL  &&  ::IsWindow(__pWnd->GetSafeHwnd()));
    m_hWnd = __pWnd->GetSafeHwnd();
    m_hDC  = ::GetDCEx(m_hWnd, NULL, DCX_CACHE);
}

// constructor initialised with a Win32 windows handle
inline CDynamicDC::CDynamicDC(HWND __hWnd)
  : m_hDC(NULL),
    m_hWnd(NULL)
{
    ASSERT(__hWnd != NULL  &&  ::IsWindow(__hWnd));
    m_hWnd = __hWnd;
    m_hDC  = ::GetDCEx(m_hWnd, NULL, DCX_CACHE);
}

// virtual destructor will free the DC
inline CDynamicDC::~CDynamicDC()
{
    if (m_hDC != NULL)
    {
        ASSERT(m_hWnd != NULL  &&  ::IsWindow(m_hWnd));
        ::ReleaseDC(m_hWnd, m_hDC);
    }
}

// this operator implements dynamic conversion to a Win32 HDC object so that
// an instance of this class can be used anywhere an HDC is expected
inline CDynamicDC::operator HDC()
{
    return m_hDC;
}

// this operator implements dynamic conversion to an MFC CDC object so that
// an instance of this class can be used anywhere a pointer to a CDC object
// is expected
inline CDC *CDynamicDC::operator->()
{
    return CDC::FromHandle(m_hDC);
}

// this operator enables an instance of this class to be dereferenced as if
// it were a pointer to an MFC CDC object, for example if a CDC reference
// is required
inline CDynamicDC::operator CDC*()
{
    return CDC::FromHandle(m_hDC);
}