我继承了Listview以执行一些小的更改,但我想改进usercontrol类或Form Class中的任何地方的设计,因为我对默认的大小调整不满意Listview的机制。
在表单类中,我调整了最后一列(" Download"),如下所示:
ColumnDownload.AutoResize(ColumnHeaderAutoResizeStyle.HeaderSize)
问题是当(默认)滚动条出现在列表视图中时,最后一列的大小不会自动固定/减少,因此水平和未嵌入的滚动条也会自动显示。
然后有人可以帮我解释一下如何在滚动条出现时自动修复最后一列的大小?我很失落。
注意:我需要说我不是在寻找其他LV,例如 ObjectListView 。
注意2 :我没有显示我的用户控制课程,因为我现在没有执行任何自动调整大小的改进,我没有'知道从哪里开始。
这是我正常的Listview:
这与填充项目的列表视图相同:
答案 0 :(得分:3)
when the (default) scrollbar appears inside the listview the size of the last column is not automatically fixed/decreased
..."默认滚动条"用来表示Veritical Scroll。
AutoResize
不是AutoFit
。它用于根据页眉文本范围或内容长度调整列的大小,而不是管理滚动条并且工作得很好。如果它确实自动调整了最后一列的大小,当最后一栏很小时,我们会生气吗?好的?'键入自动装配时无法读取的列。
PInvokes在NativeMethods
班级;这些吃滚动条,并得到它们是否显示。
Public Const WS_VSCROLL As Integer = &H200000
Public Const WS_HSCROLL As Integer = &H100000
Friend Enum SBOrientation As Integer
SB_HORZ = &H0
SB_VERT = &H1
SB_CTL = &H2
SB_BOTH = &H3
End Enum
<DllImport("user32.dll")> _
Private Shared Function ShowScrollBar(ByVal hWnd As IntPtr,
ByVal wBar As Integer,
<MarshalAs(UnmanagedType.Bool)> ByVal bShow As Boolean
) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowLong(ByVal hWnd As IntPtr,
ByVal nIndex As Integer) As Integer
End Function
Friend Shared Function IsHScrollVisible(ByVal ctl As Control) As Boolean
Dim wndStyle As Integer = GetWindowLong(ctl.Handle, GWL_STYLE)
Return ((wndStyle And WS_HSCROLL) <> 0)
End Function
Friend Shared Function IsVScrollVisible(ByVal ctl As Control) As Boolean
Dim wndStyle As Integer = GetWindowLong(ctl.Handle, GWL_STYLE)
Return ((wndStyle And WS_VSCROLL) <> 0)
End Function
Friend Shared Sub ShowHideScrollBar(ByVal ctl As Control,
ByVal sb As SBOrientation, ByVal bShow As Boolean)
ShowScrollBar(ctl.Handle, sb, bShow)
End Sub
从最后一列中窃取xx像素;如果VScroll消失,则将像素放回原位。
基本上发生的事情是ClientSizeChanged
发生两次:1)当VScroll到达时,然后在HScroll由于VScroll而到达时再次出现几个微观。所以你必须处理两次事件。这将在第一遍中调整所需列的大小,并在第二行中调用HScroll。即使在步骤1之后不再需要HScroll,如果您不手动删除它,它会短暂显示。
如果由于你的布局方式或用户调整列的大小而需要HScroll,它会调整最后一列的大小,但不会吃掉HScroll。缺少检测何时不需要第一步的额外逻辑(您通常无法看到它执行此操作)。
警告:我不知道这是否适用于第三方主题。我不认为主题可以修改这些内部滚动条。
另外,这个用于子类LV ,我知道你已经完成了。对于其他人,通过对参考文献进行一些修改,这也应该适用于“推送”的表格。使用相关事件(例如ClientSizeChanged
)的更改,即使它在表单中留下了许多丑陋的代码。
这也不包含在IF AutoFit
属性测试中。
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
把它放在ISupportInitialize.EndInit
:
orgClient = Me.ClientRectangle
Sub New 不是orgClient
的好地方 - 尚未创建控件。 OnHandleCreated
会这样做,但如果没有ISupportInitialize
,我会在控件上调用一个新的Sub来代替Form_Load。如果你想重新启动,这实际上很方便。手动调整列后再重新生成的东西。例如:
' method on subclassed LV: from form load: thisLV.ResetClientSize
Public Sub ResetClientSize
orgClient = Me.ClientRectangle
End Sub
' a helper:
Private Function AllColumnsWidth() As Integer
Dim w As Integer = 0
For Each c As ColumnHeader In Columns
w += c.Width
Next
Return w
End Function
' The Meat
Protected Overrides Sub OnClientSizeChanged(ByVal e As System.EventArgs)
Dim VScrollVis As Boolean
Dim HScrollVis As Boolean
' get who is Now Showing...local vars
VScrollVis = NativeMethods.IsVScrollVisible(Me)
HScrollVis = NativeMethods.IsHScrollVisible(Me)
' width change
Dim delta As Integer = (orgClient.Width - ClientRectangle.Width)
Dim TotalWidth As Integer = AllColumnsWidth()
If (TotalWidth < ClientRectangle.Width - _VScrollWidth) And
(_resizedCol = -1) Then
Exit Sub
End If
Me.SuspendLayout()
' If VScroll IS showing, but WASNT showing the last time thru here
' ... then we are here because VScroll just appeared.
' That being the case, trim the desired column
If VScrollVis And _VScroll = False Then
' a smarter version finds the widest column and resizes THAT one
_resizedCol = Columns.Count - 1
' we have to wait for the HScroll to show up
' to remove it
Columns(_resizedCol).Width -= (delta + 1)
End If
' HScroll just appeared
If HScrollVis And (delta = _VScrollWidth) Then
' HScroll popped up, see if it is needed
If AllColumnsWidth() <= orgClient.Width Then
' no, go away foul beast !
NativeMethods.ShowHideScrollBar(Me,
NativeMethods.SBOrientation.SB_HORZ, False)
_HScroll = False ' hopefully
' allows us to set it back if the VScroll disappears
orgClient = ClientRectangle
Else
' ToDo: use this to detect when none of this is needed
_HScroll = HScrollVis
End If
End If
' If VScroll ISNOT showing, but WAS showing the last time thru here
' ...then we are here because VScroll disappeared
If VScrollVis = False And _VScroll = True Then
' put back the pixels
If _resizedCol <> -1 Then
Columns(_resizedCol).Width += (_VScrollWidth + 1)
' reset column tracker
_resizedCol = -1
' reset to new compare size
orgClient = ClientRectangle
End If
End If
_VScroll = VScrollVis
Me.ResumeLayout()
End Sub
答案 1 :(得分:0)
或多或少我已经完成了所以我发布了这个解决方案,代码仍有问题&#39;因为在某些我尝试过的情况下它没有按预期工作&# 34;播放&#34;显示和隐藏滚动条,它可以挂起列表视图,并确保代码有不必要的检查,可以改进,但现在我没有更多的时间来尝试修复相关的问题,如果有人可以帮助修复此代码然后改进它,那么多:
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