ListView Final Column Autosize creates scrollbar

前端 未结 8 1281
闹比i
闹比i 2021-01-13 18:23

I am implementing a custom control which derives from ListView.

I would like for the final column to fill the remaining space (Quite a common task), I have gone abou

8条回答
  •  北荒
    北荒 (楼主)
    2021-01-13 19:12

    ObjectListView (an open source wrapper around .NET WinForms ListView) allows this "expand-last-column-to-fill-available-space". It's actually more difficult to get right than it first appears -- do not believe anyone who tells you otherwise :)

    If you use ObjectListView, you get the solution to that problem -- and several others -- for free. But if you want to do all the work yourself, you'll need to:

    • use ClientSize instead of DisplayRectangle (as @zxpro has already said)
    • use Layout event rather than Resize event.
    • listen for ColumnResized event and do the same work
    • not do the auto resizing in design mode -- it gets very confusing.

    The trickiest problem only appears when the window shrinks -- the horizontal scroll bar flickers annoyingly and sometimes remains after the shrinking is finished. Which appears to be exactly what is happening in your case.

    The solution is to intercept the WM_WINDOWPOSCHANGING message and resize the ListView to what the new size is going to be.

    protected override void WndProc(ref Message m) {
        switch (m.Msg) {
            case 0x46: // WM_WINDOWPOSCHANGING
                this.HandleWindowPosChanging(ref m);
                base.WndProc(ref m);
                break;
            default:
                base.WndProc(ref m);
                break;
        }
    }
    
    protected virtual void HandleWindowPosChanging(ref Message m) {
        const int SWP_NOSIZE = 1;
    
        NativeMethods.WINDOWPOS pos = (NativeMethods.WINDOWPOS)m.GetLParam(typeof(NativeMethods.WINDOWPOS));
        if ((pos.flags & SWP_NOSIZE) == 0) {
            if (pos.cx < this.Bounds.Width) // only when shrinking
                // pos.cx is the window width, not the client area width, so we have to subtract the border widths
                this.ResizeFreeSpaceFillingColumns(pos.cx - (this.Bounds.Width - this.ClientSize.Width));
        }
    }
    

提交回复
热议问题