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
http://bbs.csdn.net/topics/390488347