Listview Column width

Started by Jonathan Bristow, February 08, 2007, 05:53:33 AM

Previous topic - Next topic

Jonathan Bristow

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?

TechSupport

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

Jean-Pierre LEROY

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

Jean-Pierre LEROY

Hello Paul,

Can you reproduce this problem ? did you get the same message as me ?

Thank you,
Jean-Pierre.

TechSupport

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.

Jonathan Bristow

Sorry for delay, but thanks Paul for this code, it works extemely well.

Roger Garstang

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.

Jean-Pierre LEROY

#7
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:


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:


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