Click here to Skip to main content
11,636,300 members (78,708 online)
Click here to Skip to main content

Flicker Free Drawing In MFC

, 25 Mar 2002 CPOL 785.6K 14.3K 298
Rate this:
Please Sign up or sign in to vote.
A simple animation example which is used to show CMemDC in several modes

Sample Image
A simple animation example which is used to show CMemDC in several mode

Introduction

Removing flicker from an MFC application is well-covered territory. You can find the topic addressed in books, and on-line. However, the techniques presented are somewhat complicated and are usually difficult to add to an existing application. One often-presented technique is called double buffering. Double buffering allows the new screen to be drawn in off-screen memory, and then the completed screen is bit-blited back onto the physical screen.

This article presents a class called CMemDC that encapsulates most of the issues associated with writing to off-screen buffers. Adding CMemDC to an existing application or MFC Active X control is nearly trivial.

Modifying an MFC Application to use CMemDC

  • Add the file memdc.h in your project.
  • Add the line #include "memdc.h" to stdafx.h.
  • Add a windows message handler for WM_ERASEBKGND.
  • Change the code in the message handler as follows:
    // Change this code
    BOOL CExampleView::OnEraseBkgnd(CDC* pDC) 
    {
          // TODO: Add your message handler code here and/or call default
          return CView::OnEraseBkgnd(pDC);
    }
     
    // To this code
    BOOL CExampleView::OnEraseBkgnd(CDC* pDC) 
    {
          return FALSE;
    }
  • Change your OnDraw code to the following:
    void CExampleView::OnDraw(CDC* dc)
    {
        CMemDC pDC(dc);
        CExampleDoc* pDoc = GetDocument();
        ASSERT_VALID(pDoc);
        // TODO: add draw code for native data here - use pDC 
         //as the device context to draw to
    }

Compile your code after you've made these changes and you will notice that the flicker you had seen before is gone.

Modifying a MFC Active X Control to use CMemDC

To add CMemDC support you follow the instruction for adding the support to an application, however you make one small change in the OnDraw function.

void CParticleTestCtlCtrl::OnDraw(CDC* pdc, const CRect& rcBounds, 
                                  const CRect& rcInvalid)
{
    CMemDC pDC(pdc, &rcBounds);
    // TODO: add draw code for native data here
    // - use pDC as the device context to draw 
}

The only substantial difference is that the rcBounds is passed to the CMemDC constructor.

Source Code

#ifndef _MEMDC_H_
#define _MEMDC_H_
 
//////////////////////////////////////////////////
// CMemDC - memory DC
//
// Author: Keith Rule
// Email:  keithr@europa.com
// Copyright 1996-2002, Keith Rule
//
// You may freely use or modify this code provided this
// Copyright is included in all derived versions.
//
// History - 10/3/97 Fixed scrolling bug.
//               Added print support. - KR
//
//       11/3/99 Fixed most common complaint. Added
//            background color fill. - KR
//
//       11/3/99 Added support for mapping modes other than
//            MM_TEXT as suggested by Lee Sang Hun. - KR
//
//       02/11/02 Added support for CScrollView as supplied
//             by Gary Kirkham. - KR
//
// This class implements a memory Device Context which allows
// flicker free drawing.
 
class CMemDC : public CDC {
private:       
    CBitmap    m_bitmap;        // Offscreen bitmap
    CBitmap*       m_oldBitmap; // bitmap originally found in CMemDC
    CDC*       m_pDC;           // Saves CDC passed in constructor
    CRect      m_rect;          // Rectangle of drawing area.
    BOOL       m_bMemDC;        // TRUE if CDC really is a Memory DC.
public:
    
    CMemDC(CDC* pDC, const CRect* pRect = NULL) : CDC()
    {
        ASSERT(pDC != NULL); 
 
        // Some initialization
        m_pDC = pDC;
        m_oldBitmap = NULL;
        m_bMemDC = !pDC->IsPrinting();
 
        // Get the rectangle to draw
        if (pRect == NULL) {
             pDC->GetClipBox(&m_rect);
        } else {
             m_rect = *pRect;
        }
 
        if (m_bMemDC) {
             // Create a Memory DC
             CreateCompatibleDC(pDC);
             pDC->LPtoDP(&m_rect);
 
             m_bitmap.CreateCompatibleBitmap(pDC, m_rect.Width(), 
                                                  m_rect.Height());
             m_oldBitmap = SelectObject(&m_bitmap);
 
             SetMapMode(pDC->GetMapMode());
 
             SetWindowExt(pDC->GetWindowExt());
             SetViewportExt(pDC->GetViewportExt());
 
             pDC->DPtoLP(&m_rect);
             SetWindowOrg(m_rect.left, m_rect.top);
        } else {
             // Make a copy of the relevent parts of the current 
             // DC for printing
             m_bPrinting = pDC->m_bPrinting;
             m_hDC       = pDC->m_hDC;
             m_hAttribDC = pDC->m_hAttribDC;
        }
 
        // Fill background 
        FillSolidRect(m_rect, pDC->GetBkColor());
    }
    
    ~CMemDC()      
    {          
        if (m_bMemDC) {
             // Copy the offscreen bitmap onto the screen.
             m_pDC->BitBlt(m_rect.left, m_rect.top, 
                           m_rect.Width(),  m_rect.Height(),
                  this, m_rect.left, m_rect.top, SRCCOPY);            
             
             //Swap back the original bitmap.
             SelectObject(m_oldBitmap);        
        } else {
             // All we need to do is replace the DC with an illegal
             // value, this keeps us from accidentally deleting the 
             // handles associated with the CDC that was passed to 
             // the constructor.              
             m_hDC = m_hAttribDC = NULL;
        }       
    }
    
    // Allow usage as a pointer    
    CMemDC* operator->() 
    {
        return this;
    }       
 
    // Allow usage as a pointer    
    operator CMemDC*() 
    {
        return this;
    }
};
 
#endif

License

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

Share

About the Author

Keith Rule
Software Developer (Senior)
United States United States
I work at Tektronix in Beaverton OR. I've been programming for fun since 1975 (I started while in a Computer Explorer Scout group in Spokane WA). I've been programming in C since 1979 and I've been working professionally since 1983.

I really enjoy www.codeproject.com. It has saved me an incredible amount of time. I only hope my small contributions have given back some of what I've taken.

You may also be interested in...

Comments and Discussions

 
Questionstill flickering Pin
Member 109214303-Jul-14 0:47
memberMember 109214303-Jul-14 0:47 
GeneralMy vote of 5 Pin
Member 1089899126-Jun-14 7:36
memberMember 1089899126-Jun-14 7:36 
GeneralMy vote of 5 Pin
WebBiscuit15-Sep-13 11:50
memberWebBiscuit15-Sep-13 11:50 
QuestionIs needed DeleteDC() ? Pin
JiHyung Lee027-Jan-13 15:36
memberJiHyung Lee027-Jan-13 15:36 
QuestionBig Thanks! Pin
sally Fields5-Nov-12 12:42
membersally Fields5-Nov-12 12:42 
QuestionProblems with CScrollView Pin
UrbanBlues3-Feb-12 20:48
memberUrbanBlues3-Feb-12 20:48 
Hello

Env: VS 2010
I use CMemDC in a CScrollView-based app.. Works great when zoom is 100%. Flicker is gone.. Works great also when I change the zoom ratio from 25% to 400%... But, with a zoom ratio higher than 100%, background is not updated correctly when I scroll the view using the scroll bars
Thanks for any clue ...
AnswerRe: Problems with CScrollView Pin
AndersBlom29-May-12 22:53
memberAndersBlom29-May-12 22:53 
GeneralMy vote of 5 Pin
=asm=1-Sep-11 0:24
member=asm=1-Sep-11 0:24 
QuestionCo-existing with CMemDC from MFC Pin
Jason Steenstra-Pickens19-Apr-11 21:05
memberJason Steenstra-Pickens19-Apr-11 21:05 
AnswerRe: Co-existing with CMemDC from MFC Pin
MatrixDud29-Apr-11 9:40
memberMatrixDud29-Apr-11 9:40 
GeneralRe: Co-existing with CMemDC from MFC Pin
Ben Aldhouse18-Aug-11 21:27
memberBen Aldhouse18-Aug-11 21:27 
GeneralMy vote of 5 Pin
yiguro13-Jan-11 1:34
memberyiguro13-Jan-11 1:34 
GeneralThanks a lot!!!! Pin
yiguro13-Jan-11 1:32
memberyiguro13-Jan-11 1:32 
GeneralMy vote of 5 Pin
bogdan3478-Jan-11 22:57
memberbogdan3478-Jan-11 22:57 
GeneralMemory leak after override OnEraseBkgnd method Pin
Penghui9-Jun-10 6:19
memberPenghui9-Jun-10 6:19 
GeneralCMemDC and scaling paint Pin
npuleio2-Feb-10 4:35
membernpuleio2-Feb-10 4:35 
GeneralLicense Concern Pin
aitieng31-Jan-10 15:22
memberaitieng31-Jan-10 15:22 
GeneralRe: License Concern Pin
Keith Rule31-Jan-10 20:11
memberKeith Rule31-Jan-10 20:11 
QuestionRe: License Concern Pin
EstelD22-Jun-10 11:14
memberEstelD22-Jun-10 11:14 
AnswerRe: License Concern Pin
Keith Rule22-Jun-10 11:47
memberKeith Rule22-Jun-10 11:47 
GeneralRe: License Concern Pin
EstelD20-Jul-10 8:45
memberEstelD20-Jul-10 8:45 
GeneralOn W7 high cpu usage. Pin
spallotti23-Dec-09 5:10
memberspallotti23-Dec-09 5:10 
GeneralSetProcessDefaultLayOut LAYOUT_RTL Pin
Farid Z27-Oct-09 18:36
memberFarid Z27-Oct-09 18:36 
GeneralRe: SetProcessDefaultLayOut LAYOUT_RTL Pin
Phil Rodgers23-Feb-10 0:57
memberPhil Rodgers23-Feb-10 0:57 
GeneralRe: SetProcessDefaultLayOut LAYOUT_RTL [modified] Pin
Farid Z23-Feb-10 15:15
memberFarid Z23-Feb-10 15:15 
NewsMFC Feature Pack for Visual C++ 2008 Pin
mykel20-Oct-09 7:54
membermykel20-Oct-09 7:54 
GeneralRe: MFC Feature Pack for Visual C++ 2008 Pin
Keith Rule20-Oct-09 10:01
memberKeith Rule20-Oct-09 10:01 
GeneralRe: MFC Feature Pack for Visual C++ 2008 Pin
mykel21-Oct-09 0:22
membermykel21-Oct-09 0:22 
GeneralRe: MFC Feature Pack for Visual C++ 2008 Pin
tmpuserz22-Mar-11 12:03
membertmpuserz22-Mar-11 12:03 
GeneralRe: MFC Feature Pack for Visual C++ 2008 Pin
Bart10-Jun-11 22:39
memberBart10-Jun-11 22:39 
GeneralThanks Pin
xsm_12612-Jun-09 21:48
memberxsm_12612-Jun-09 21:48 
Answer... Pin
Member 426330222-Feb-09 20:06
memberMember 426330222-Feb-09 20:06 
QuestionCDialog Based application with memdc.h and MSFlexgrid Control Pin
tmg5128117-Feb-09 3:03
membertmg5128117-Feb-09 3:03 
GeneralThanks~!! Pin
Member 377536112-Feb-09 14:09
memberMember 377536112-Feb-09 14:09 
GeneralVery good job !!! Pin
raymondnana29-Jan-09 3:24
memberraymondnana29-Jan-09 3:24 
Generalcool... Pin
auralius21-Dec-08 18:11
memberauralius21-Dec-08 18:11 
GeneralCMemDC & Dialog Menu Pin
Steven Pence8-Dec-08 9:38
memberSteven Pence8-Dec-08 9:38 
QuestionHow to use in Controls? Pin
blamond30-Apr-08 11:14
memberblamond30-Apr-08 11:14 
AnswerRe: How to use in Controls? Pin
blamond6-May-08 8:52
memberblamond6-May-08 8:52 
Generalchild windows Pin
toddma9-Nov-07 10:16
membertoddma9-Nov-07 10:16 
GeneralThanks for some greate time / pain saving! Pin
SoftwareGeek8-Nov-07 0:08
memberSoftwareGeek8-Nov-07 0:08 
GeneralNice work, but... Pin
SimpleProgrammer15-Aug-07 5:51
memberSimpleProgrammer15-Aug-07 5:51 
GeneralRe: Nice work, but... Pin
brian.lee5-Sep-07 20:47
memberbrian.lee5-Sep-07 20:47 
GeneralNot recognising CDC members Pin
facelaunch3-Aug-07 6:53
memberfacelaunch3-Aug-07 6:53 
QuestionStill flickering Pin
facelaunch3-Aug-07 9:13
memberfacelaunch3-Aug-07 9:13 
AnswerRe: Still flickering Pin
facelaunch3-Aug-07 9:55
memberfacelaunch3-Aug-07 9:55 
GeneralRe: Not recognising CDC members Pin
GuptaP16-Aug-07 8:25
memberGuptaP16-Aug-07 8:25 
GeneralRe: Not recognising CDC members Pin
JDENISW14-Jun-09 8:55
memberJDENISW14-Jun-09 8:55 
QuestionDisplay non-solid-color background in scroll-view correctly Pin
chen_zd11-Jun-07 2:45
memberchen_zd11-Jun-07 2:45 
GeneralThank u. Pin
Murali_mom30-May-07 21:16
memberMurali_mom30-May-07 21:16 

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 | Terms of Use | Mobile
Web03 | 2.8.150728.1 | Last Updated 26 Mar 2002
Article Copyright 1999 by Keith Rule
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid