自绘控件中经常会遇到闪烁的问题,主要原因是某个区域发生了重复性的绘制而导致的,而列表控件在自绘后闪烁原因是WM_ERASEBKGND消息所导致的。解决定办法可以将这个消息屏蔽掉,然后使用双缓存,在Windows 5.1版本以后可以使用LVS_EX_DOUBLEBUFFER样式,为了各个版本的兼容性我个人不建议使用这个样式,因此我们可以拦截WM_PAINT消息来使用我们自已创建的双缓存,具体看代码所示:
1.屏蔽WM_ERASEBKGND消息
BOOL CMyListCtrl::OnEraseBkgnd(CDC
*
pDC)
{
return FALSE;
}
{
return FALSE;
}
2.在WM_PAINT消息中使用自已的双缓存
void
CMyListCtrl::OnPaint()
{
CPaintDC dc(this);
CRect rcClient,rcClip,rcHeader;
GetClientRect(&rcClient);
GetHeaderCtrl()->GetWindowRect(&rcHeader);
dc.GetClipBox(&rcClip);
CDC MemDC;
CBitmap MemBitmap, *pOldBitmap;
MemDC.CreateCompatibleDC(&dc);
int nMode = MemDC.SetMapMode(dc.GetMapMode());
MemBitmap.CreateCompatibleBitmap(&dc,rcClient.Width(),rcClient.Height());
pOldBitmap = MemDC.SelectObject(&MemBitmap);
MemDC.FillSolidRect(&rcClient,GetBkColor());
CRgn rgn;
rgn.CreateRectRgn(rcClip.left,rcClip.top,rcClip.right,rcClip.bottom);
MemDC.SelectClipRgn(&rgn);
DefWindowProc(WM_PAINT,(WPARAM)MemDC.m_hDC,(LPARAM)0);
MemDC.SelectClipRgn(NULL);
if (rcClip.top < rcHeader.Height())
rcClip.top = rcHeader.Height();
dc.BitBlt(rcClip.left,rcClip.top,rcClip.Width(),rcClip.Height(),&MemDC,rcClip.left,rcClip.top,SRCCOPY);
MemDC.SetMapMode(nMode);
MemDC.SelectObject(pOldBitmap);
MemDC.DeleteDC();
MemBitmap.DeleteObject();
rgn.DeleteObject();
}
{
CPaintDC dc(this);
CRect rcClient,rcClip,rcHeader;
GetClientRect(&rcClient);
GetHeaderCtrl()->GetWindowRect(&rcHeader);
dc.GetClipBox(&rcClip);
CDC MemDC;
CBitmap MemBitmap, *pOldBitmap;
MemDC.CreateCompatibleDC(&dc);
int nMode = MemDC.SetMapMode(dc.GetMapMode());
MemBitmap.CreateCompatibleBitmap(&dc,rcClient.Width(),rcClient.Height());
pOldBitmap = MemDC.SelectObject(&MemBitmap);
MemDC.FillSolidRect(&rcClient,GetBkColor());
CRgn rgn;
rgn.CreateRectRgn(rcClip.left,rcClip.top,rcClip.right,rcClip.bottom);
MemDC.SelectClipRgn(&rgn);
DefWindowProc(WM_PAINT,(WPARAM)MemDC.m_hDC,(LPARAM)0);
MemDC.SelectClipRgn(NULL);
if (rcClip.top < rcHeader.Height())
rcClip.top = rcHeader.Height();
dc.BitBlt(rcClip.left,rcClip.top,rcClip.Width(),rcClip.Height(),&MemDC,rcClip.left,rcClip.top,SRCCOPY);
MemDC.SetMapMode(nMode);
MemDC.SelectObject(pOldBitmap);
MemDC.DeleteDC();
MemBitmap.DeleteObject();
rgn.DeleteObject();
}