c++ - 删除和重新添加所有项目和所有列时,Listview 在 Win32 对话框中闪烁

标签 c++ mfc listview winapi listctrl

考虑用 C++ 编写的带有 ListView 控件(在报告模式下)的普通 Win32 对话框。在发生特定事件时,所有项目和所有列都将被删除并创建新的列和项目。基本上,随着内容的变化,列会根据内容自动生成。

当删除旧项目/列并添加新项目/列时, ListView 会像 hell 一样闪烁。我已经尝试过 WM_SETREDRAWLockWindowUpdate(),视觉体验没有任何变化。

我什至设置了扩展 ListView 样式LVS_EX_DOUBLEBUFFER,但一点用都没有。

父对话框设置了 WS_CLIPCHILDREN

有什么建议可以使这项工作尽可能少的闪烁吗?我正在考虑使用两个 ListView ,交替可见性,使用隐藏的 ListView 作为后台缓冲区,但这听起来有点矫枉过正。必须有一个简单的方法。

最佳答案

默认的列表控件绘制有很大的缺陷。但是有一个简单的技巧可以实现您自己的双缓冲技术:

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);
    }
}

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

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

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

这将阻止控件在重绘之前始终删除背景。 如果您为位图添加一个成员变量并且仅在窗口大小更改时(重新)创建它,您可以进一步优化 OnPaint(因为根据窗口的大小,始终创建位图可能会花费大量的时间)。

这应该工作得很好。

关于c++ - 删除和重新添加所有项目和所有列时,Listview 在 Win32 对话框中闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3150108/

相关文章:

java - 从扩展 ArrayAdapter 的类中获取 ListView 自定义 friend

Android:listview 中的 inflater 是什么?

永远不会调用 android ListView onOverScroll

c++ - 如何在 Qt for Embedded Linux 中定位和使用字体?

c++ - win32编程子窗口没有退出按钮

c++ - CPU 架构的 8 位 FFT?

c++ - MS Sans Serif 在 XP 中无法显示 Unicode 文本,但在 Win7 中可以

c++ - GetSystemTime() wHour 没有提供正确的值 MFC C++

c++ - 自动引用 vector ?

c++ - 从 CEdit 派生类更改文本和背景颜色