Click here to Skip to main content
Click here to Skip to main content

CAutoPen class - a CPen that IS correctly destroyed

, 24 Nov 1999
Rate this:
Please Sign up or sign in to vote.
<!-- Article Starts -->

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 -->

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 -->

// 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

About the Author

Anneke Sicherer-Roetman
Web Developer
Netherlands Netherlands
No Biography provided

Comments and Discussions

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

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.140709.1 | Last Updated 25 Nov 1999
Article Copyright 1999 by Anneke Sicherer-Roetman
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid