Flickering in listview with ownerdraw and virtualmode

后端 未结 3 1132
我在风中等你
我在风中等你 2020-12-15 14:47

I\'m using listview control with the following parameters set:

        this.listView1.BackColor = System.Drawing.Color.Gainsboro;
        this.listView1.Colu         


        
3条回答
  •  北海茫月
    2020-12-15 15:11

    This is a bug in .NET's ListView and you cannot get around it by double buffering.

    On virtual lists, the underlying control generates lots of custom draw events when the mouse is hover over column 0. These custom draw events cause flickering even if you enable DoubleBuffering because they are sent outside of the normal WmPaint msg.

    I also seem to remember that this only happens on XP. Vista fixed this one (but introduced others).

    You can look in at the code in ObjectListView to see how it solved this problem.

    If you want to solve it yourself, you need to delve into the inner plumbing of the ListView control:

    1. override WndProc
    2. intercept the WmPaint msg, and set a flag that is true during the msg
    3. intercept the WmCustomDraw msg, and ignore all msgs that occur outside of a WmPaint event.

    Something like this::

    protected override void WndProc(ref Message m) {
        switch (m.Msg) {
            case 0x0F: // WM_PAINT
                this.isInWmPaintMsg = true;
                base.WndProc(ref m);
                this.isInWmPaintMsg = false;
                break;
            case 0x204E: // WM_REFLECT_NOTIFY
                NativeMethods.NMHDR nmhdr = (NativeMethods.NMHDR)m.GetLParam(typeof(NativeMethods.NMHDR));
                if (nmhdr.code == -12) { // NM_CUSTOMDRAW
                    if (this.isInWmPaintMsg)
                        base.WndProc(ref m);
                } else
                    base.WndProc(ref m);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }
    

提交回复
热议问题