last column width in listview (report view)
Hi,
Does anyone know an easy way I can make the width of the LAST column header in a 'report view' listview automatically be equal to the space available.
ie,
if the other columns take up half the width of the listview, the last column takes up the other half.
Similary, if the width of one of the other columns changes, the width of the last column is automatically changed appropiately (so there is never a horizontal scroll bar).
Thanks in advance for any help you can give me.
Tom.
Re: last column width in listview (report view)
Hi
This problem is probably better split into 2 parts.
1. The resizing of the last column
2. The capturing of the column resize and resizing the columns appropriately
For this post I'll just stick to number 1. Number 2 involves subclassing the ListView to capture the Column Resize event. I've written an article about this on the CodeGuru site (see http://www.codeguru.com/vb/articles/htm/LVTricks.shtml). The article shows how to disable resizing but you could quite easily replace it with your own code.
To resize the last column in the listview, you'll need to determine whether your listview already has a horizontal scrollbar. If it has, then we're not interested in resizing the last column. Otherwise, we want to resize the last column to fill up the remainder of the listview (but not cause a Horizontal Scrollbar to appear).
Here's the code from the sample form I wrote. Place a listview onto the form with two buttons (command1 and command2), then paste in the following code :
Option Explicit
Private Const LVSCW_AUTOSIZE As Long = -1
Private Const LVM_FIRST = &H1000
Private Const LVM_GETCOLUMNWIDTH As Long = LVM_FIRST + 29
Private Const WM_SETREDRAW = &HB
Private Const LVM_SETCOLUMNWIDTH As Long = LVM_FIRST + 30
'
Private Const SM_CXVSCROLL = 2 ' Get Width Of Vertical ScrollBar
Private Const WS_HSCROLL = &H100000
Private Const GWL_STYLE = (-16)
'
Private Declare Function LockWindowUpdate Lib "user32" (ByVal hwndLock As Long) As Long
Private Declare Function SendMessageLong Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long
Private Declare Function GetSystemMetrics Lib "user32" (ByVal nIndex As Long) As Long
Private Function HasHorizontalScrollBar(ByVal lHwnd As Long) As Boolean
'
' General purpose routine to see if ANY control has a Horizontal ScrollBar
'
Dim lStyle As Long
lStyle = GetWindowLong(hwnd, GWL_STYLE)
HasHorizontalScrollBar = lStyle And WS_HSCROLL
End Function
Private Sub Command1_Click()
Dim lCount As Long
'
' This button does an auto resize of all the columns :
'
'
' Turn off Redrawing at this point to speed up / hide the visible changes
'
LockWindowUpdate ListView1.hwnd
For lCount = 0 To ListView1.ColumnHeaders.Count - 1
SendMessageLong ListView1.hwnd, LVM_SETCOLUMNWIDTH, lCount, LVSCW_AUTOSIZE
Next
LockWindowUpdate ByVal 0&
End Sub
Private Sub Command2_Click()
Dim lCount As Long
Dim lNoColumns As Long
Dim lTotSize As Long
Dim lRet As Long
Dim lSize As Long
Dim lHScrollBarWidth As Long
'
' This button will size the listview if no Horizontal scrollbar is displayed
'
'
' Get System defined width of the Horizontal ScrollBars
'
lHScrollBarWidth = GetSystemMetrics(SM_CXVSCROLL)
'
' Get Number of columns in this listview
'
lNoColumns = ListView1.ColumnHeaders.Count
'
' Check if it has a Horizontal Scrollbar
'
If HasHorizontalScrollBar(ListView1.hwnd) Then
'
' Don't do anything if it has ... otherwise ...
'
Else
For lCount = 0 To lNoColumns - 2
'
' Get the total size of all the columns except the last one we want to resize
'
lSize = SendMessageLong(ListView1.hwnd, LVM_GETCOLUMNWIDTH, lCount, 0)
lTotSize = lTotSize + lSize
Next
'
' Now determine how big to make the last columm in pixels
'
lSize = (ListView1.Width / Screen.TwipsPerPixelX) - (lTotSize + lHScrollBarWidth + 10)
'
' Now set the column width
'
SendMessageLong ListView1.hwnd, LVM_SETCOLUMNWIDTH, lNoColumns - 1, lSize
End If
End Sub
Private Sub Form_Load()
Dim lCount As Long
Dim li As ListItem
'
' Populate the listview with some random junk strings
'
With ListView1
.View = lvwReport
For lCount = 1 To 4
.ColumnHeaders.Add , , "Column " & lCount
Next
For lCount = 1 To 3000
Set li = .ListItems.Add(, , String$((Rnd(1) * 20), "X"))
li.SubItems(1) = String$(Rnd(1) * 15, "1")
li.SubItems(2) = String$(Rnd(1) * 15, "2")
li.SubItems(3) = String$(Rnd(1) * 15, "3")
Next
End With
End Sub
Hope it helps
Chris Eastwood
Software Engineer
ACNielsen Ltd
http://www.codeguru.com