C# 自动将列适配到垂直滚动条的Listview

C# 自动将列适配到垂直滚动条的Listview,c#,.net,vb.net,winforms,listview,C#,.net,Vb.net,Winforms,Listview,我继承了一个Listview来执行一些小的更改,但我想改进usercontrol类或Form类中任何地方的设计,因为我不喜欢Listview的默认大小调整机制 在Form类中,我调整最后一列(“下载”)的大小,如下所示: ColumnDownload.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize) 问题在于,当(默认)滚动条出现在listview内部时,最后一列的大小不会自动固定/减小,因此也会自动出现一个水平和未插入的滚动条 然后有人可以

我继承了一个Listview来执行一些小的更改,但我想改进usercontrol类或Form类中任何地方的设计,因为我不喜欢Listview的默认大小调整机制

在Form类中,我调整最后一列(“下载”)的大小,如下所示:

ColumnDownload.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize)
问题在于,当(默认)滚动条出现在listview内部时,最后一列的大小不会自动固定/减小,因此也会自动出现一个水平和未插入的滚动条

然后有人可以帮我解释一下,当滚动条出现时,如何自动修复最后一列的大小?我对那件事很迷茫

注意:我需要说的是,我不是在寻找替代的LV,比如ObjectListView

注意2:我没有显示我的usercontrol类,因为我目前没有执行任何自动调整大小的改进,我不知道从哪里开始

这是我的Listview(正常情况下):

这是同一个列表视图,其中填充了项目:


或多或少我已经完成了,所以我会发布这个解决方案,代码仍然有问题,因为在某些情况下,我试图“播放”显示和隐藏滚动条,但它可能会挂起listview,当然,代码已经不需要检查,可以改进,但是现在我没有更多的时间来尝试修复相关问题,如果有人可以帮助修复此代码以改进它,那么非常感谢:

Dim SizeAlreadyDecreased As Boolean = False

Private Sub ElektroListView_Downloads_ClientSizeChanged(sender As Object, e As EventArgs) _
Handles ElektroListView_Downloads.ClientSizeChanged

    ' Retrieve all the column widths
    Dim AllColumnsWidth As Integer =
        (From col As ColumnHeader In CType(sender.Columns, ListView.ColumnHeaderCollection)
         Select col.Width).Sum

    ' Fix the last column width to fill the not-used blank space when resizing the Form.
    Me.ColumnDownload.Width =
        Me.ColumnDownload.Width + (sender.ClientSize.Width - AllColumnsWidth) - 2

    ' Fix the last column width to increase or decrease the size if a VertivalScrollbar appears.
    If GetScrollbars(sender) AndAlso Not SizeAlreadyDecreased Then
        SizeAlreadyDecreased = True
        ColumnDownload.Width -= SystemInformation.VerticalScrollBarWidth

    ElseIf GetScrollbars(sender) AndAlso SizeAlreadyDecreased Then
        SizeAlreadyDecreased = True

    ElseIf Not GetScrollbars(sender) AndAlso SizeAlreadyDecreased Then
        SizeAlreadyDecreased = False
        ColumnDownload.Width += SystemInformation.VerticalScrollBarWidth

    ElseIf Not GetScrollbars(sender) AndAlso Not SizeAlreadyDecreased Then
        SizeAlreadyDecreased = False

    End If

End Sub

Private Const WS_VSCROLL As Integer = &H200000I
Private Const WS_HSCROLL As Integer = &H100000I
Private Const GWL_STYLE As Integer = -16I

<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function GetWindowLong(
        ByVal hWnd As HandleRef,
        ByVal nIndex As Integer
) As Integer
End Function

Public Function GetScrollbars(ByVal ctrl As Control) As ScrollBars

    Dim style As Integer = GetWindowLong(New HandleRef(ctrl, ctrl.Handle), GWL_STYLE)

    Dim HScroll As Boolean = ((style And WS_HSCROLL) = WS_HSCROLL)
    Dim VScroll As Boolean = ((style And WS_VSCROLL) = WS_VSCROLL)

    If (HScroll AndAlso VScroll) Then
        Return ScrollBars.Both

    ElseIf HScroll Then
        Return ScrollBars.Horizontal

    ElseIf VScroll Then
        Return ScrollBars.Vertical

    Else
        Return ScrollBars.None

    End If

End Function
Dim sizealreadydreduced为Boolean=False
Private Sub-ElektroListView\u Downloads\u ClientSizeChanged(发件人作为对象,e作为事件参数)_
处理ElektroListView_Downloads.ClientSizeChanged
'检索所有列宽
Dim AllColumnsWidth为整数=
(作为CType(sender.Columns,ListView.ColumnHeaderCollection)中的ColumnHeader从col开始)
选择列宽度)
'调整表单大小时,请固定最后一列宽度以填充未使用的空白。
Me.columnload.Width=
Me.columnload.Width+(sender.ClientSize.Width-AllColumnsWidth)-2
'如果出现VertivalScrollbar,请固定最后一列宽度以增大或减小大小。
如果GetScrollbars(sender)和大小也未减小,则
sizealreadydreduced=True
ColumnDownload.Width-=SystemInformation.VerticalScrollBarWidth
ElseIf GetScrollbars(发送方)和大小也已减小
sizealreadydreduced=True
否则,如果未获取滚动条(发送方)和大小也已减小,则
sizealreadydreduced=False
ColumnDownload.Width+=SystemInformation.VerticalScrollBarWidth
否则,如果未获取滚动条(发送方)且大小也未减小,则
sizealreadydreduced=False
如果结束
端接头
私有常量WS_VSCROLL作为整数=&H200000I
私有常量WS_HSCROLL为整数=&H100000I
Private Const GWL_样式为整数=-16I
私有共享函数GetWindowLong(
ByVal hWnd作为HandleRef,
ByVal nIndex作为整数
)作为整数
端函数
公共函数GetScrollbars(ByVal ctrl作为控件)作为滚动条
作为整数的Dim样式=GetWindowLong(新HandleRef(ctrl,ctrl.Handle),GWL_样式)
将HScroll设置为布尔值=((样式和wshscroll)=wshscroll)
将VScroll标注为布尔=((样式和WS_VScroll)=WS_VScroll)
如果(HScroll和also VScroll),则
返回滚动条。两者都有
那么艾尔塞夫·赫斯克罗尔呢
返回滚动条。水平
那么艾尔塞夫·维斯克罗尔呢
返回滚动条。垂直
其他的
返回滚动条。无
如果结束
端函数
当(默认)滚动条出现在列表视图中时,最后一列的大小不会自动固定/减小
。。。“默认滚动条”表示真实滚动条

AutoResize
不是
AutoFit
。它用于根据标题文本范围或内容长度调整列大小,而不是管理滚动条,效果非常好。如果它确实自动调整了最后一列的大小,那么当最后一列是一个小的“OK”类型的列时,我们会很生气,因为当它被自动装配时,该列变得不可读

NativeMethods
类中的pinvoke;这些会吃掉滚动条,并获取滚动条是否显示

Public Const WS_VSCROLL As Integer=&H200000
公共常量WS_HSCROLL为整数=&H100000
友元枚举作为整数
SB_HORZ=&H0
SB_垂直=&H1
SB_CTL=&H2
SB_两者=&H3
结束枚举
_
专用共享功能显示滚动条(ByVal hWnd作为IntPtr,
ByVal wBar作为整数,
ByVal bShow作为布尔值
)作为布尔值
端函数
_
私有共享函数GetWindowLong(ByVal hWnd作为IntPtr,
ByVal nIndex(作为整数)作为整数
端函数
好友共享函数(ByVal ctl作为控件)为布尔值
Dim wndStyle As Integer=GetWindowLong(ctl.Handle,GWL_样式)
返回((wndStyle和wshscroll)0)
端函数
朋友共享函数IsVScrollVisible(ByVal ctl作为控件)作为布尔值
Dim wndStyle As Integer=GetWindowLong(ctl.Handle,GWL_样式)
返回((wndStyle和WS_VSCROLL)0)
端函数
好友共享子ShowHideScrollBar(ByVal ctl作为控件,
ByVal sb作为sb方向,ByVal bShow作为布尔值)
显示滚动条(控制手柄、sb、bShow)
端接头
从最后一列偷取xx个像素;如果VScroll消失,请将像素放回原处。

基本上,发生的情况是
ClientSizeChanged
触发两次:1)当VScroll到达时,然后在几微秒后,当HScroll作为VScroll的结果到达时再次触发。因此,您必须处理事件两次。这将在第一个过程中调整所需列的大小,并在第二个过程中吃掉HScroll。尽管在步骤1之后不再需要HSCROL,但如果您不删除它,它会短暂显示
Private orgClient As Rectangle      ' original client size for comparing
Private _VScrollWidth As Integer 

Private _resizedCol As Integer = -1
Private _VScroll As Boolean = False    ' persistent Scroll flags 
Private _HScroll As Boolean = False

' 3rd party???
_VScrollWidth = System.Windows.Forms.SystemInformation.VerticalScrollBarWidth
orgClient = Me.ClientRectangle