我在启用了 LVS_EX_DOUBLEBUFFER
的虚拟模式 (LVS_OWNERDATA
) 中使用 CListCtrl/CListView 报告 View (LVS_REPORT
),我遇到了难看的问题闪烁。双缓冲有一个真正的效果,但它不会停止所有闪烁(没有它非常慢)。
我不想切换到需要大量返工的其他控件(如 ObjectListView)
闪烁的行为如何:
- 在调整列大小时 - 首先使用浅灰色清洁背景,然后显示文本(背景为白色)
- 鼠标滚动(动画)- 在要显示新行的区域中会显示一个浅灰色条,时间很短。
看起来它确实使用默认窗口背景颜色(浅灰色)清理了必须重绘区域的背景。
如何解决闪烁问题?
最佳答案
尝试执行以下操作: - 为List Control 的paremt 对话框设置Clip Children 和Clip Sibling。 - 从 CListCtrl 类中提取。在这个类中覆盖 OnEraseBkgnd。在 OnEraseBkgnd 中,用列表可见项周围的背景颜色区域填充。 OnEraseBkgnd 看起来像:
BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC)
{
CBrush br;
CRect rcCli;
CRect rcItemsRect(0, 0, 0, 0);
int nHeadHeight = 0;
int nItems = GetItemCount();
GetClientRect(&rcCli);
CHeaderCtrl* pHeadCtrl = GetHeaderCtrl();
if (pHeadCtrl)
{
CRect rcHead;
pHeadCtrl->GetWindowRect(&rcHead);
nHeadHeight = rcHead.Height();
}
rcCli.top += nHeadHeight;
if (nItems > 0)
{
CPoint ptItem;
CRect rcItem;
GetItemRect(nItems - 1, &rcItem, LVIR_BOUNDS);
GetItemPosition(nItems - 1, &ptItem);
rcItemsRect.top = rcCli.top;
rcItemsRect.left = ptItem.x;
rcItemsRect.right = rcItem.right;
rcItemsRect.bottom = rcItem.bottom;
if (GetExtendedStyle() & LVS_EX_CHECKBOXES)
rcItemsRect.left -= GetSystemMetrics(SM_CXEDGE) + 16;
}
br.CreateSolidBrush(GetBkColor());
if (rcItemsRect.IsRectEmpty())
pDC->FillRect(rcCli, &br);
else
{
if (rcItemsRect.left > rcCli.left) // fill left rectangle
pDC->FillRect(
CRect(0, rcCli.top, rcItemsRect.left, rcCli.bottom), &br);
if (rcItemsRect.bottom < rcCli.bottom) // fill bottom rectangle
pDC->FillRect(
CRect(0, rcItemsRect.bottom, rcCli.right, rcCli.bottom), &br);
if (rcItemsRect.right < rcCli.right) // fill right rectangle
pDC->FillRect(
CRect(rcItemsRect.right, rcCli.top, rcCli.right, rcCli.bottom), &br);
}
return TRUE;
}
关于c++ - 如何防止 CListCtrl 闪烁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2486682/