![]() |
Multimedia »
GDI »
Device Contexts
Intermediate
Flicker Free Drawing In MFCBy Keith RuleA simple animation example which is used to show CMemDC in several modes |
VC6, Windows, MFC, GDI, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||

A simple animation example which is used to show CMemDC in several mode
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.
WM_ERASEBKGND.
// 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; }
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.
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.
#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
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 25 Mar 2002 Editor: Chris Maunder |
Copyright 1999 by Keith Rule Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |