WTL的双缓存类非常好用,但是要注意一点。这个DoPaint的重载函数中,只有传递给WM_PAINT中CPaintDC中的m_ps.rcPaint区域才能更新,其他区域将无法得到更新。这点需要了解下。
如果你在缓存DoPaint( CDCHandle dc) 获取的DC中,在rcPaint之外的绘图将无法在屏幕上显示。因为这个内存缓存只把rcPaint中的部分作为一个bitmap映射,其他部分没有映射。因此会越界的。
解决的方法就是不要使用InvalidateRect,直接使用InvalidateWindow。或者修改程序,把那个rcPaint传过来,自己DoPaint的时候小心。
修改的方法,可以参照atltheme.h中的CBufferedPaintImpl,把那个rect也一起传进来
/////////////////////////////////////////////////////////////////////////////// // CBufferedPaintImpl - provides buffered paint for any window template <class T> class ATL_NO_VTABLE CBufferedPaintImpl : public CBufferedPaintBase { public: CBufferedPaint m_BufferedPaint; BP_BUFFERFORMAT m_dwFormat; BP_PAINTPARAMS m_PaintParams; // Overrideables void DoBufferedPaint(CDCHandle dc, RECT& rect) { HDC hDCPaint = NULL; if(IsBufferedPaintSupported()) m_BufferedPaint.Begin(dc, &rect, m_dwFormat, &m_PaintParams, &hDCPaint); T* pT = static_cast<T*>(this); if(hDCPaint != NULL) pT->DoPaint(hDCPaint, rect); //修改成类似这样 else pT->DoPaint(dc.m_hDC, rect); //修改成类似这样 if(IsBufferedPaintSupported()) m_BufferedPaint.End(); } void DoPaint(CDCHandle /*dc*/, RECT& /*rect*/) { // must be implemented in a derived class ATLASSERT(FALSE); } };
我修改成这样
/////////////////////////////////////////////////////////////////////////////// // CDoubleBufferImpl - Provides double-buffer painting support to any window template <class T> class CDoubleBufferImpl { public: // Overrideables void DoPaint(CDCHandle /*dc*/,RECT& /*rect*/) //这里修改 { // must be implemented in a derived class ATLASSERT(FALSE); } // Message map and handlers BEGIN_MSG_MAP(CDoubleBufferImpl) MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground) MESSAGE_HANDLER(WM_PAINT, OnPaint) #ifndef _WIN32_WCE MESSAGE_HANDLER(WM_PRINTCLIENT, OnPaint) #endif // !_WIN32_WCE END_MSG_MAP() LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { return 1; // no background painting needed } LRESULT OnPaint(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/) { T* pT = static_cast<T*>(this); ATLASSERT(::IsWindow(pT->m_hWnd)); if(wParam != NULL) { RECT rect = { 0 }; pT->GetClientRect(&rect); CMemoryDC dcMem((HDC)wParam, rect);//修改 pT->DoPaint(dcMem.m_hDC,rect); } else { CPaintDC dc(pT->m_hWnd); CMemoryDC dcMem(dc.m_hDC, dc.m_ps.rcPaint); pT->DoPaint(dcMem.m_hDC, dc.m_ps.rcPaint);//修改 } return 0; } };
参考:
http://www.cnblogs.com/wdhust/archive/2011/01/12/1934042.html