I can change the listview column width no problem, but how do i automatically adjust the column width according to the text in each column and column header data?
Below is some sample code that I threw together after finding a C example on the Net. It seems to work really well and allows you to specify one or all columns to autosize and a minimum size for the column.
Function FORM1_WM_CREATE ( _
hWndForm As Dword, _ ' handle of Form
ByVal UserData As Long _ 'optional user defined Long value
) As Long
FF_ListView_DeleteAllItems HWND_FORM1_LISTVIEW1
FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 0, "Column1", 0, 100
FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 1, "Column2", 0, 100
FF_ListView_InsertColumn HWND_FORM1_LISTVIEW1, 2, "Column3", %LVCFMT_RIGHT, 100
For row& = 0 To 10
For col& = 0 To 2
FF_ListView_InsertItem HWND_FORM1_LISTVIEW1, row&, col&, String$(Rnd(1, 25), "x"), 0, 0
Next
Next
ListView_AutoSizeColumns HWND_FORM1_LISTVIEW1, 10, -1 ' -1 to resize all columns rather than just one column
End Function
Function ListView_GetColumnCount( ByVal hWndListView As Dword ) As Dword
Local hWndLVHdr As Dword
'// get the header control
hWndLVHdr = SendMessage( hWndListView, %LVM_GETHEADER, 0, 0 )
'// return the number of items in it - ie. the number of columns
Function = SendMessage( hWndLVHdr, %HDM_GETITEMCOUNT, 0, 0 )
End Function
Function ListView_AutoSizeColumns( ByVal hWndListView As Dword, _
ByVal nMinSize As Long, _
ByVal col As Long _
) As Long
Local mincol As Long
Local maxcol As Long
Local wc As Long
Local wc1 As Long
Local wc2 As Long
' If you don't supply a column number, it will resize all columns. If you do
' supply a column numner, it will resize that column only. For example, you
' may only want to resize the first column when you do label editing (or
' another column if you use inplace cell editing or combos). But you might
' want to resize all columns after loading the list control with data.
SendMessage hWndListView, %WM_SETREDRAW, %FALSE, 0
mincol = IIf&( col < 0, 0, col )
maxcol = IIf&( col < 0, ListView_GetColumnCount(hWndListView)-1, col )
For col = mincol To maxcol
FF_ListView_SetColumnWidth hWndListView, col, %LVSCW_AUTOSIZE
wc1 = FF_ListView_GetColumnWidth( hWndListView, col )
FF_ListView_SetColumnWidth hWndListView, col, %LVSCW_AUTOSIZE_USEHEADER
wc2 = FF_ListView_GetColumnWidth( hWndListView, col )
wc = Max( nMinSize, Max(wc1,wc2) )
FF_ListView_SetColumnWidth hWndListView, col, wc
Next
SendMessage hWndListView, %WM_SETREDRAW, %TRUE, 0
FF_Control_Redraw hWndListView
End Function
Hello Paul and thank you for this code; I was looking for such a function for a long time.
For your information, I get an error "Undefined equate" for %HDM_GETITEMCOUNT if I check "Dynamically create CommCtrl.inc exclude equates" in FireFly "Environment Options/Code Generation".
Thank you,
Jean-Pierre
Hello Paul,
Can you reproduce this problem ? did you get the same message as me ?
Thank you,
Jean-Pierre.
Yes, I also get the same error.
In FireFly 3, there will be no such thing as that option to dynamically create the exclude equates. That power will now rest in the hands of the user.
Sorry for delay, but thanks Paul for this code, it works extemely well.
That is a lot of work to do something that is built in. (%LVSCW_AUTOSIZE_USEHEADER uses the max of Header and Text length) Check out the last lines of my code:
http://www.planetsquires.com/forums/viewtopic.php?t=2216
Also see:
http://vbnet.mvps.org/index.html?code/comctl/lvcolumnautosize.htm
The FF functions even mentioned these, although you may want to add to the descriptions. And if you actually use a Listview you shouldn't get any issues with the Dynamic Equates. My only problem with them was when using ToolTips, but you added the Force Init Common Controls option to fix that. I kinda like the option, so unless we have an INClean solution??? My code usually doubles in compile size without the option. It would be nice to have a spot to put equates other than in the "General" Section above functions. Some place that when compiling gets put above/before any code.
Hi,
when I use the function ListView_AutoSizeColumns(), the last column is always resized to occupy the remaining width in the control; see the result below:
(http://listview_autosizecolumns.jpg)
So I create a new function called ListView_ResizeAllColumns() that resize the last column based only on the width of the widest list item in the last column; see the result below:
(http://listview_resizeallcolumns.jpg)
Here is the code for this function; there is an optional parameter called pLastColumnsMinSize if you want the last column to be at a minimum width.
I don't know if it is the best code to get this result, but it works.
Sub ListView_ResizeAllColumns( ByVal hWndListView As Dword, _
Opt ByVal pLastColumnMinSize As Long)
Local col As Long
Local wc As Long
Local wc1 As Long
Local wc2 As Long
Local lNbColumns As Long
lNbColumns = ListView_GetColumnCount(hWndListView)-1
SendMessage hWndListView, %WM_SETREDRAW, %FALSE, 0
' to set all the columns of the ListView
For col = 0 To lNbColumns
' Size each column based on the width of the widest list item in the column.
FF_ListView_SetColumnWidth hWndListView, col, %LVSCW_AUTOSIZE
wc1 = FF_ListView_GetColumnWidth( hWndListView, col )
' Size each column based on the maximum of the column header text width
' except for the last column
If col <> lNbColumns Then
FF_ListView_SetColumnWidth hWndListView, col, %LVSCW_AUTOSIZE_USEHEADER
wc2 = FF_ListView_GetColumnWidth( hWndListView, col )
Else
wc2 = pLastColumnMinSize
End If
' Size the column based on the max
wc = Max(wc1,wc2)
FF_ListView_SetColumnWidth hWndListView, col, wc
Next col
SendMessage hWndListView, %WM_SETREDRAW, %TRUE, 0
FF_Control_Redraw hWndListView
End Sub