考虑使用C ++编写的ListView Control(在报告模式下)的普通Win32对话框。在某个事件中,所有项目和所有列均已删除,并创建了新的列和项目。基本上,随着内容的变化,列是根据内容自动生成的。

当删除旧项目/列并添加新项目时,ListView Flickers如Hell。我试过了 WM_SETREDRAWLockWindowUpdate() 没有改变视觉体验。

我什至设置了扩展的ListView样式 LVS_EX_DOUBLEBUFFER 这根本没有帮助。

父母对话框 WS_CLIPCHILDREN 放。

有什么建议如何使此功能尽可能少地闪烁?我正在考虑使用两个listViews,交替的可见性,使用隐藏的视野作为后缓冲区,但这听起来像是过度的。必须有一种简单的方法。

有帮助吗?

解决方案

默认列表控制绘画非常有缺陷。但是,有一个简单的技巧来实现自己的双重屏蔽技术:

CMyListCtrl::OnPaint()
{
    CRect rcClient;
    GetClientRect(rcClient);

    CPaintDC dc(this);
    CDC dcMem;
    dcMem.CreateCompatibleDC(&dc);

    CBitmap bmMem;
    bmMem.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
    CBitmap* pbmOld = dcMem.SelectObject(&bmMem);

    dcMem.FillSolidRect(rcClient, ::GetSysColor(COLOR_WINDOW));

    this->DefWindowProc(WM_PAINT, (WPARAM)dcMem.m_hDC, (LPARAM)0);

    dc.BitBlt(0,0,rcClient.Width(), rcClient.Height(), &dcMem, 0, 0, SRCCOPY);
    dcMem.SelectObject(pbmOld);

    CHeaderCtrl*    pCtrl = this->GetHeaderCtrl();
    if (::IsWindow(pCtrl->GetSafeHWnd())
    {
        CRect   aHeaderRect;
        pCtrl->GetClientRect(&aHeaderRect);
        pCtrl->RedrawWindow(&aHeaderRect);
    }
}

这将创建一个位图,然后调用默认窗口过程以将列表控件绘制到位图中,然后将位图的内容闪烁到油漆DC中。

您还应该为WM_ERASEBKND添加一个处理程序:

BOOL CMyListCtrl::OnEraseBkgnd(CDC* pDC)
{
    return TRUE;
}

这将阻止控件在重新修复之前始终擦除背景。如果您为位图添加成员变量,则可以进一步优化OnPaint,并且仅在窗口的大小更改时(RE)创建它(因为始终创建一个位图可能会取决于窗口的大小)。

这应该很好。

其他提示

在尝试了很多事情之后 humbagumba我的建议得出了一个非常简单的结论。 LockWindowUpdate 在这种情况下,每个人都是朋友。我不确定它是怎么对我第一次工作,但是在自定义绘画之后,我尝试过的所有情况下都无法交付 LockWindowUpdate 再次起作用!

基本上,只需在listView上包装所有工作 LockWindowUpdate(hWnd)LockWindowUpdate(NULL) 而且事情正常工作。甚至不再有滚动片闪烁。

只是确保不要筑巢 LockWindowUpdate 因为一次只能锁定一个窗口。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top