The
Listview control in both VB5 and VB6 implementations supports SendMessage with the LVSCW_AUTOSIZE and LVSCW_AUTOSIZE_USEHEADER messages to
cause the Listview to adjust its column widths to maximize data display. This page shows how to use these messages to resize the columns to
fit the longest column item, to fit the longest column item or column header, whichever is wider, and to resize only the last column to fill
any unused Listview view area.
The top form shows the control column layout when the app has started
based on its default settings.
The next illustration shows the results with the LVSCW_AUTOSIZE message applied - each column has been sized to a width determined by its longest
list item. Where the list item data is narrower than the column header text, that header text is truncated. Illustration three uses the
LVSCW_AUTOSIZE_USEHEADER message - note that the caption for each column header is fully visible. Finally the last illustration shows how
applying the LVSCW_AUTOSIZE_USEHEADER message to only the last column will cause the column to occupy the remaining width in the control (as
indicated by the red arrow). By altering this last example (i.e. passing a column index) you could create a fourth method to resize only
specific columns.
This page contains all the code required to complete the demo as
shown. |
Option Explicit
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Copyright ©1996-2011 VBnet/Randy Birch, All Rights Reserved.
' Some pages may also contain other copyrights by the author.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
' Distribution: You can freely use this code in your own
' applications, but you may not reproduce
' or publish this code on any web site,
' online service, or distribute as source
' on any media without express permission.
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_SETCOLUMNWIDTH As Long = (LVM_FIRST + 30)
Private Const LVSCW_AUTOSIZE As Long = -1
Private Const LVSCW_AUTOSIZE_USEHEADER As Long = -2
Private Declare Function SendMessage Lib "user32" _
Alias "SendMessageA" _
(ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Sub Form_Load()
Dim sItem As String
Dim dwbuff As Long
Dim dbuff As Date
Dim r As Long
Dim l As Long
Dim t As Long
Dim w As Long
Dim cnt As Long
Dim sLen As Long
Dim itmx As ListItem
Randomize
sItem = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit."
sLen = (Len(sItem) / 2)
With ListView1
.ColumnHeaders.Add , , "Main column"
.ColumnHeaders.Add , , "Sub col 1"
.ColumnHeaders.Add , , "Sub col 2"
.ColumnHeaders.Add , , "Sub col 3"
.View = lvwReport
'add random data of varying length
For cnt = 1 To 20
r = Int(Rnd * sLen) + 1
dbuff = CDate(Int(Rnd * 5484) + 33219)
Set itmx = ListView1.ListItems.Add(, , Left$(sItem, r))
itmx.SubItems(1) = Format$(Int(Rnd * 2000) + 1, "###,###")
itmx.SubItems(2) = Format$(dbuff, "yyyy MMM d")
itmx.SubItems(3) = IIf(cnt Mod 3, "Etiam", "Hendrerit")
Next
End With
l = ListView1.Left
t = ListView1.Top + ListView1.Height + 100
w = (ListView1.Width - 200) \ 3
With Command1
.Move l, t, w, 345
.Caption = "Size to Content"
End With
With Command2
.Move Command1.Left + Command1.Width + 100, t, w, 345
.Caption = "Size to Header"
End With
With Command3
.Move Command2.Left + Command2.Width + 100, t, w, 345
.Caption = "Maximize Width"
End With
End Sub
Private Sub Command1_Click()
'Size each column based on the width
'of the widest list item in the column.
'If the items are shorter than the column
'header text, the header text is truncated.
'You may need to lengthen column header
'captions to see this effect.
Dim col2adjust As Long
For col2adjust = 0 To ListView1.ColumnHeaders.Count - 1
Call SendMessage(ListView1.hwnd, _
LVM_SETCOLUMNWIDTH, _
col2adjust, _
ByVal LVSCW_AUTOSIZE)
Next
End Sub
Private Sub Command2_Click()
'Size each column based on the maximum of
'EITHER the column header text width, or,
'if the items below it are wider, the
'widest list item in the column.
'
'The last column is always resized to occupy
'the remaining width in the control.
Dim col2adjust As Long
For col2adjust = 0 To ListView1.ColumnHeaders.Count - 1
Call SendMessage(ListView1.hwnd, _
LVM_SETCOLUMNWIDTH, _
col2adjust, _
ByVal LVSCW_AUTOSIZE_USEHEADER)
Next
End Sub
Private Sub Command3_Click()
'Because applying LVSCW_AUTOSIZE_USEHEADER
'to the last column in the control always
'sets its width to the maximum remaining control
'space, calling SendMessage passing just the
'last column index will resize only the last column,
'resulting in a listview utilizing the full
'control width space. To see this resizing in practice,
'create a wide listview and press the "Size to Contents"
'button followed by the "Maximize Width" button.
'By explanation: if a listview had a total width of 2000
'and the first three columns each had individual widths of 250,
'calling this will cause the last column to widen
'to cover the remaining 1250.
'Calling this will force the data to remain within the
'listview. If a column other than the last column is
'widened or narrowed, the last column will become
'sized to ensure all data remains within the control.
'This could truncate text depending on the overall
'widths of the other columns; the minimum width is still
'based on the length of that column's header text.
Dim col2adjust As Long
col2adjust = ListView1.ColumnHeaders.Count - 1
Call SendMessage(ListView1.hwnd, _
LVM_SETCOLUMNWIDTH, _
col2adjust, _
ByVal LVSCW_AUTOSIZE_USEHEADER)
End Sub
|