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:
- Ease of use. Simply instantiate the object with a window handle and use it as a DC
- Guaranteed and Automatic release of system DC resource.
- 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
- 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();
CDC *operator->();
operator CDC*();
};
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);
}
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);
}
inline CDynamicDC::~CDynamicDC()
{
if (m_hDC != NULL)
{
ASSERT(m_hWnd != NULL && ::IsWindow(m_hWnd));
::ReleaseDC(m_hWnd, m_hDC);
}
}
inline CDynamicDC::operator HDC()
{
return m_hDC;
}
inline CDC *CDynamicDC::operator->()
{
return CDC::FromHandle(m_hDC);
}
inline CDynamicDC::operator CDC*()
{
return CDC::FromHandle(m_hDC);
}