CMemDC:在MFC下解决绘图闪烁

简介
在MFC应用程序解决闪烁是一个很常见的问题。我们可以在书或网上找到很多这样的材料。然而,这些技术多少有些复杂且难以运用到一个已有的应用程序中。双缓冲就是一个最常用的解决这个问题的技术。双缓冲就是在离屏内存中绘制一张图形,然后把绘制完成的图像按像素一次性贴到物理显示屏上。

这篇文章给出一个叫CMemDC的类,这个类封装了绘制离屏缓冲区的操作。因此,向一个已经存在的应用程序或者ActiveX控件中添加CMemDC来解决闪烁问题是件非常简单的事情。

如何用CMemDC修改MFC应用程序
把memdc.h添加到你的工程中
在stdafx.h中添加#include "memdc.h"
为WM_ERASEBKGND消息添加windows消息处理函数
然后对消息处理函数做如下改动:

view plaincopy to clipboardprint?
// 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 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函数做出如下改动:
          view plaincopy to clipboardprint?
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  

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
}

做出如上改动后编译你的代码,你就会发现闪烁问题已经被你解决了。

如何用CMemDC修改一个MFC Active X空间
要用CMemDC你只需要在OnDraw函数中做出一点很小的改变,如下:

          view plaincopy to clipboardprint?
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   

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
}

唯一一点区别就是rcBounds是通过CMemDC的构造函数传递的。

源代码
          view plaincopy to clipboardprint?
#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 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/boyzk2008/archive/2009/03/29/4033249.aspx


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/boyzk2008/archive/2009/03/29/4033249.aspx

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值