Visual Basic Common Control API Routines
SendMessage: Auto-size ListView Column Width
     
Posted:   Saturday February 12, 2000
Updated:   Monday December 26, 2011
     
Applies to:   VB4-32, VB5, VB6
Developed with:   VB6, Windows NT4
OS restrictions:   None
Author:   VBnet - Randy Birch
     
 Prerequisites
None. This method works with both the Visual Basic 5 and Visual Basic 6 Common Control Listview.

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.

 BAS Module Code
None.

 Form Code
Create a form similar containing one Listview (Listview1) and three command buttons (Command1, Command2, Command3) and add the following code:

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
 Comments

 
 

PayPal Link
Make payments with PayPal - it's fast, free and secure!

 
 
 
 

Copyright ©1996-2011 VBnet and Randy Birch. All Rights Reserved.
Terms of Use  |  Your Privacy

 

Hit Counter