Click here to Skip to main content
15,886,720 members
Articles / Multimedia / GDI

CAutoPen Class - A CPen that IS Correctly Destroyed

Rate me:
Please Sign up or sign in to vote.
4.86/5 (7 votes)
24 Nov 1999 61.9K   18   5
CAutoPen Class - a CPen that is correctly destroyed

If you create a temporary CPen object on the stack with one of the one-step CPen constructors, you can easily forget to deselect the pen from the device context before it goes out of scope. In that case, although stepping through the code and running BoundsChecker will make you believe otherwise, this causes a serious GDI resource leak. The CAutoPen class overcomes this flaw and also selects the pen into the device context in the constructors. MFC is a much too thin wrapper around Win32!!!

Example of the usage of a CAutoPen (and a CAutoBrush): <!-- start a block of source code -->

C++
void CMyView::OnDraw(CDC* pDC)
{
  // make red pen
  CAutoPen NewPen(pDC, PS_SOLID, 1, RGB(255,0,0));
  // make green brush
  CAutoBrush NewBrush(pDC, RGB(0, 255, 0));
  // draw rectangle
  CRect rect(10, 10, 110, 110);
  pDC->Rectangle(&rect);
  // and automatic cleanup done
}

Source code of CAutoPen and CAutoBrush: <!-- start a block of source code -->

C++
// Filename:      AutoPen.h
// Programmer:    Anneke Sicherer-Roetman - a.sicherer@noldus.nl
//                Noldus Information Technology, Wageningen, Netherlands
// Revision Date: 1999-04-09
// Description:   Classes CAutoPen & CAutoBrush

#if !defined AUTOPEN_H
#define AUTOPEN_H

class CAutoPen : public CPen
{

public:

  // 1st constructor, see CPen docs
  CAutoPen(CDC *pDC, int nPenStyle, int nWidth, COLORREF crColor) :
  CPen(nPenStyle, nWidth, crColor), m_pDC(pDC), m_pOldGdi(NULL) 
  { 
    Initialize();  
  }

  // 2nd constructor, see CPen docs
  CAutoPen(CDC *pDC, int nPenStyle, int nWidth, const LOGBRUSH *pLogBrush,
           int nStyleCount = 0, const DWORD *lpStyle = NULL) :
  CPen(nPenStyle, nWidth, pLogBrush, nStyleCount, lpStyle), m_pDC(pDC), m_pOldGdi(NULL)
  { 
    Initialize();  
  }

  // destructor, deselects pen from device context
  virtual ~CAutoPen()
  { 
    ASSERT_VALID(m_pOldGdi);
    ASSERT_VALID(m_pDC);
    m_pDC->SelectObject(m_pOldGdi);
  }

private:

  CDC        *m_pDC;      // remembers device context
  CGdiObject *m_pOldGdi;  // remembers previous pen

  CAutoPen() { }          // default constructor cannot be called

  // selects pen into device context
  void Initialize() 
  {
    m_pOldGdi = m_pDC->SelectObject(this); 
    ASSERT_VALID(m_pOldGdi);
  }

};

class CAutoBrush : public CBrush
{

public:

  // 1st constructor, see CBrush docs
  CAutoBrush(CDC *pDC, COLORREF crColor) :
  CBrush(crColor), m_pDC(pDC), m_pOldGdi(NULL)
  { 
    Initialize();  
  }

  // 2nd constructor, see CBrush docs
  CAutoBrush(CDC *pDC, int nIndex, COLORREF crColor) :
  CBrush(nIndex, crColor), m_pDC(pDC), m_pOldGdi(NULL)
  { 
    Initialize();  
  }

  // 3rd constructor, see CBrush docs
  CAutoBrush(CDC *pDC, CBitmap* pBitmap) :
  CBrush(pBitmap), m_pDC(pDC), m_pOldGdi(NULL)
  { 
    Initialize();  
  }

  // destructor, deselects brush from device context
  virtual ~CAutoBrush()
  { 
    ASSERT_VALID(m_pOldGdi);
    ASSERT_VALID(m_pDC);
    m_pDC->SelectObject(m_pOldGdi);
  }

private:

  CDC        *m_pDC;      // remembers device context
  CGdiObject *m_pOldGdi;  // remembers previous pen

  CAutoBrush() { }        // default constructor cannot be called

  // selects brush into device context
  void Initialize() 
  {
    m_pOldGdi = m_pDC->SelectObject(this); 
    ASSERT_VALID(m_pOldGdi);
  }

};

#endif

License

This article has no explicit license attached to it, but may contain usage terms in the article text or the download files themselves. If in doubt, please contact the author via the discussion board below.

A list of licenses authors might use can be found here.


Written By
Web Developer
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVery solid technique used ... Pin
WREY25-Jun-04 5:31
WREY25-Jun-04 5:31 
GeneralTake a look at the article that I wrote in 1998 Pin
Michael S. Scherotter10-Dec-02 10:25
Michael S. Scherotter10-Dec-02 10:25 
GeneralRe: Take a look at the article that I wrote in 1998 Pin
WREY25-Jun-04 6:15
WREY25-Jun-04 6:15 
GeneralRe: Take a look at the article that I wrote in 1998 Pin
peterchen1-Nov-04 7:34
peterchen1-Nov-04 7:34 
GeneralSeparate out pen and DC Pin
Feng Yuan28-Jan-00 23:44
Feng Yuan28-Jan-00 23:44 

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.