ListView_AutoSize


Description:
This is the programmatic equivalent of hitting <Ctrl>+<Gray Plus> on a ListView. This also demonstrates how to get around an apparent bug in the ListView control when setting and getting column widths by using API calls to do the same.
 
Code:
Option Explicit

Private Const LVM_FIRST = &H1000
Private Const LVM_GETCOLUMNWIDTH = (LVM_FIRST + 29)
Private Const LVM_SETCOLUMNWIDTH = (LVM_FIRST + 30)
Private Const LVSCW_AUTOSIZE = -1
Private Const SM_CXVSCROLL = 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 Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As _
   Long) As Long
   
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock _
   As Long) As Long
   
Public Sub ListView_AutoSize( _
   lvToResize As ListView, _
   Optional bLastColumn As Boolean = True, _
   Optional bLockWin As Boolean = True)
    
    Debug.Assert lvToResize.View = lvwReport
    
    
    Dim nColumn As Long
    Dim nNewWidth As Long

    If bLockWin Then
        LockWindowUpdate lvToResize.hWnd
    End If
    
    For nColumn = 0 To lvToResize.ColumnHeaders.Count - 1
        SendMessage lvToResize.hWnd, LVM_SETCOLUMNWIDTH, nColumn, _
                    LVSCW_AUTOSIZE
    Next

    If bLastColumn Then
        For nColumn = 0 To lvToResize.ColumnHeaders.Count - 2
            nNewWidth = nNewWidth + SendMessage(lvToResize.hWnd, _
                        LVM_GETCOLUMNWIDTH, nColumn, ByVal 0)
        Next
        
        nNewWidth = nNewWidth + GetSystemMetrics(SM_CXVSCROLL)
        nNewWidth = ((lvToResize.Width / Screen.TwipsPerPixelX) - _
                    nNewWidth) - 6
        nColumn = lvToResize.ColumnHeaders.Count - 1
        If nNewWidth > 0 Then
            SendMessage lvToResize.hWnd, LVM_SETCOLUMNWIDTH, nColumn, _
                        ByVal nNewWidth
        End If
    End If

    If bLockWin Then
        LockWindowUpdate 0
    End If

End Sub


 
Sample Usage:
 
ListView_AutoSize ListView1