MFC 双缓冲实现

时间:2022-09-10 10:09:18

#pragma once
//用这个类可以实现双缓冲
/*

通过
CMemoryDC dc(pDc);  创建一个内存DC,
dc.Fill();  全部是内存Bitmap上画图
当dc析构时,将内存bitmap直接拷贝到物理DC上去.
*/
class CMemoryDC
 :public CDC
{
protected: 
   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.  
    
  void Construct(CDC* pDC) 
  { 
        ASSERT(pDC != NULL);  
 
        // Some initialization  
      m_pDC = pDC; 
      m_oldBitmap = NULL; 
      m_bMemDC = !pDC->IsPrinting(); 
 
     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()); 
          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()); 
  } 
 
// TRK begin  
public: 
   CMemoryDC(CDC* pDC     ) : CDC() { pDC->GetClipBox(&m_rect); Construct(pDC); } 
   CMemoryDC(CDC* pDC, const RECT& rect) : CDC() { m_rect = rect           ; Construct(pDC); } 
// TRK end  
    
   virtual ~CMemoryDC() 
  {         
       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 accidently deleting the handles associated with  
           // the CDC that was passed to the constructor.              
           m_hDC = m_hAttribDC = NULL; 
        }     
   } 
    
    // Allow usage as a pointer      
   CMemoryDC* operator->()  
   { 
       return this; 
   }     
 
   // Allow usage as a pointer      
   operator CMemoryDC*()  
 { 
  return this; 
 } 
};