Date: 02-16-2022
Return to Index
's the code I promised - showing how to implement the kind of Listview column resizing that you see in Microsoft Office (Outlook).
created by gbSnippets
1. When the app is re-sized, all columns expand according to the
percentage of the client area they currently cover.
2. If a user manually re-sizes a column, columns to the left are unchanged. Columns to the right are re-sized proportionately to fill all space to the right of the re-sized column.
3. When the rightmost column is resized, all columns to the left are proportionately resized to use up the freed space.
4. In all cases after resizing, there is no unused space to the right of the right-most column. All columns stay in view and the entire width of the ListView control is used by the visible columns.
5. If the user double clicks on a column divider, an action that normally re-sizes that column to match the widest data in that column, the column is allowed to expand only to the edge of ListView control, less a minimum space allotted for each columns to the right of the expanded column.
's perhaps quite a mouthful for what turns out to be only about 20 lines of code, but that short code took me almost 4 days of off-and-on coding to get right (fingers crossed!). Let me know if you have any trouble with it!
's the compilable example:
Code:
'Compilable Example: (Jose Includes)
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
%Unicode=1
#Include "Win32API.inc"
#Include "CommCtrl.inc"
%IDC_ListView = 400
Global hDlg, hListView,hListViewH,hConsole As Dword, OrigLVProc, OrigLVHProc As Long
Global CD(), Tracking As Long
Function PBMain() As Long
Dialog New Pixels, 0, "Outlook Resizing",300,300,400,150, %WS_OverlappedWindow To hDlg
CreateListViewControl
Dialog Show Modal hDlg Call DlgProc
End Function
CallBack Function DlgProc() As Long
Local w,h,wCol As Long
Select Case Cb.Msg
Case %WM_InitDialog
OrigLVProc = SetWindowLong(hListView, %GWL_WndProc, CodePtr(NewLVProc)) 'subclass
Case %WM_User + 500
ResizeColumns(Cb.WParam)
ResizeWindows
Case %WM_Size
ResizeWindows
Case %WM_Destroy
SetWindowLong hListView, %GWL_WNDPROC, OrigLVProc
End Select
End Function
Sub CreateListViewControl
Control Add ListView, hDlg, %IDC_ListView,"", 10,10,380,200
Control Handle hDlg, %IDC_ListView To hListView
ListView Insert Column hDlg, %IDC_ListView, 1, "Name", 100, 0
ListView Insert Column hDlg, %IDC_ListView, 2, "Path", 100, 0
ListView Insert Column hDlg, %IDC_ListView, 3, "Date", 100, 0
ListView Insert Column hDlg, %IDC_ListView, 4, "Size", 100, 0
ListView Insert Item hDlg, %IDC_ListView, 1,0, "First Row"
ListView Set Text hDlg, %IDC_ListView, 1, 2, "Column two data which can be very long if you let it which we will in this case"
ListView Set Text hDlg, %IDC_ListView, 1, 3, "Column three data which is long but not all that long."
ListView Set Text hDlg, %IDC_ListView, 1, 4, "This is somewhat short"
ReDim CD(4)
CD(1) = 15 : CD(2) = 60 : CD(3) = 15 : CD(4) = 10
End Sub
Function NewLVProc(ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Local hdnptr As HD_NOTIFY Ptr, hdiptr As HD_ITEM Ptr, w,iCol,wCol,iResult As Long
Select Case Msg
Case %WM_Notify
hdnptr = lParam
hdiptr = @hdnptr.pitem
Select Case @hdnptr.hdr.code
Case %hdn_DividerDblClickW
Tracking = 2
Dialog Post hDlg, %WM_User+500, @hdnptr.iItem + 1, 0
Case %hdn_TrackW
Tracking = 1
Case %hdn_EndTrackW
iResult = @hdnptr.iItem
If Tracking Then Dialog Post hDlg, %WM_User+500, @hdnptr.iItem+1, 0
End Select
End Select
Function = CallWindowProc(OrigLVProc, hWnd, Msg, wParam, lParam)
End Function
Sub ResizeWindows
Local x,y,w,h As Long
Dialog Get Client hDlg To w,h
Control Set Size hDlg, %IDC_ListView, w-20, h-20
Control Get Client hDlg, %IDC_ListView To w,h
w = w + 20 * IsTrue(GetWindowLong(hListView, %GWL_STYLE) And %WS_VScroll) 'account for scrollbar
For x = 1 To UBound(CD) : ListView Set Column hDlg, %IDC_ListView, x, CD(x) * w / 100 : Next x
End Sub
Sub ResizeColumns(ByVal iCol As Long)
Local i,j,w,h,iResult,wCol,ww, pToLeft, pToRight,pTotalW, wToLeft, m, cMin As Long
'get/set values needed to adjust column percentages
Control Get Client hDlg, %IDC_ListView To w,h 'ListView client w,h
ListView Get Column hDlg, %IDC_Listview, iCol To wCol 'width of column iCol
m = 20 'min column width - pixels
cMin = 100 * m/w 'min column width - percentage of w
'set CD(iCol) - percentage of dragged or double-clicked column
For i = 1 To iCol-1 : pToLeft = pToLeft + CD(i) : Next i '% to left of iCol
If Tracking = 2 And (pToLeft*w/100 + wCol + m*(UBound(CD)-iCol)) > w Then 'expanded width is wider than client area
wCol = w * ( 100 - cMin*(UBound(CD)-iCol) - pToLeft ) /100 'shrink wCol to fit client area
For i = iCol+1 To UBound(CD) : CD(i) = cMin : Next i 'set cols to right to specified small percentage
End If
For i = iCol+1 To UBound(CD) : pToRight = pToRight + CD(i) : Next i '% to right of iCol
CD(iCol) = 100 * wCol / w
'adjust all other appropriate columns
If iCol < UBound(CD) Then
For i = iCol+1 To UBound(CD) : CD(i) = CD(i) / pToRight * (100 - pToLeft - CD(iCol)) : Next i 'all except last column
Else
For i = 1 To iCol-1 : CD(i) = CD(i) /pToLeft * (100 - CD(iCol)) : Next i 'last column only
End If
Tracking = 0
End Sub
'gbs_01016
'Date: 03-10-2012
http://www.garybeene.com/sw/gbsnippets.htm