自绘控件中经常会遇到闪烁的问题,主要原因是某个区域发生了重复性的绘制而导致的,而列表控件在自绘后闪烁原因是WM_ERASEBKGND消息所导致的。解决定办法可以将这个消息屏蔽掉,然后使用双缓存,在Windows 5.1版本以后可以使用LVS_EX_DOUBLEBUFFER样式,为了各个版本的兼容性我个人不建议使用这个样式,因此我们可以拦截WM_PAINT消息来使用我们自已创建的双缓存,具体看代码所示:
1.屏蔽WM_ERASEBKGND消息
- BOOL CMyListCtrl::OnEraseBkgnd(CDC * pDC)
- {
- 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();
- }