代码之家  ›  专栏  ›  技术社区  ›  wpfwannabe

删除和重新添加所有项和列时,Win32对话框上的Listview闪烁

  •  3
  • wpfwannabe  · 技术社区  · 14 年前

    考虑用C++编写的ListVIEW控件(报表模式)的Win32对话框。在某个事件发生时,将删除所有项和列,并创建新的列和项。基本上,随着内容的变化,列会根据内容自动生成。

    当删除旧项/列并添加新项/列时,listview会像地狱一样闪烁。我试过了 WM_SETREDRAW LockWindowUpdate()

    我甚至还设置了扩展列表视图样式 LVS_EX_DOUBLEBUFFER 这一点用都没有。

    父对话框已打开 WS_CLIPCHILDREN 设置。

    有什么建议如何使这个工作尽可能少闪烁?我正在考虑使用两个列表视图,交替可见性,使用隐藏的一个作为后缓冲区,但这听起来像是一个过度杀伤力。一定有个简单的办法。

    2 回复  |  直到 14 年前
        1
  •  7
  •   humbagumba    14 年前

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

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

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

    您还应该为WM\u ERASEBKGND添加一个处理程序:

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

    这将阻止控件在重画之前总是擦除背景。

    这应该很管用。

        2
  •  1
  •   wpfwannabe    14 年前

    在尝试了很多事情之后 humbagumba 我得出了一个非常简单的结论。 LockWindowUpdate 在这种情况下是每个人的朋友。我不知道为什么它没有为我工作的第一次,但在定制绘画失败后,在所有的情况下,我尝试了 禁止在窗口绘图 又一次成功了!

    LockWindowUpdate(hWnd) LockWindowUpdate(NULL)

    因为一次只能锁定一个窗口。