Outlook ListView Sizing IV

Category: Controls - ListView

Date: 03-28-2012

Return to Index

All columns are always visible (cMin is observed)
Entire ListView width always used (no dead space to the right)
Manual Resize Column (non-RightMost)
1. All other columns expand proportionately.
2. Columns to the left are unchanged.
3. Columns to the right are resized proportionately to fill space to right
Manual Resize RightMost Column
1. Can only be resized smaller
2. Cannot move divider outside the ListView
3. All other columns expand proportionately to fill all available space
Manual Resizing Limitations
1. Cannot move divider farther to the left than LeftEdgeCurrentColumn + cMin
2. Cannot move divider farther to the right than ColsToLeft * cMin.
DoubleClick (non-RightMost)
11. Double-clicked divider expands on to SpaceToRight - ColsToRight*cMin
Stop divider from moving wCol < m
Stop divider from moving wCol > w-n*m
'Compilable Example:
#Compiler PBWin 9, PBWin 10
#Compile EXE
#Dim All
#Include "Win32API.inc"
#Include "CommCtrl.inc"
%IDC_ListView     = 400
Global hDlg, hListView,hListViewH,hConsole As Dword, OrigLVProc, OrigLVHProc As Long
Global CD() As Single, Tracking As Long
Function PBMain() As Long
   Dialog New Pixels, 0, "Outlook Resizing",300,300,400,150, %WS_OverlappedWindow To hDlg
   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
      Case %WM_Size
      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 LongAs 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, MsgwParamlParam)
End Function
Sub DisplayStuff
   Local sResult As Single, i, wTotal, iResult As Long, temp$
   sResult = 0 : wTotal = 0
   For i = 1 To UBound(CD)
      sResult = sResult + CD(i)
      ListView Get Column hDlg, %IDC_ListView, i To iResult
      temp$ = temp$ + Str$(iResult)
      wTotal = wTotal + iResult
   Next i
   Dialog Set Text hDlg, Str$(sResult) + Str$(wTotal) + temp$
End Sub
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 ResizeColumnsLV(ByVal iCol As Long)
   Local i,j,w,h,iResult,wCol,ww, wToLeft,wToRight,wTotal, m As Long
   Local pToLeft, pToRight, cMin As Single
   '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
   'minimum column width
   If wCol < m Then wCol = m
   'get total width of all columns, including newly resized iCol
   For i = 1 To UBound(CD)
      ListView Get Column hDlg, %IDC_ListView, i To iResult   'column width
      If i < iCol Then pToLeft = pToLeft + CD(i)   : wToLeft = wToLeft + iResult
      wTotal = wTotal + iResult
   Next i
   'if wCol is too big (either by double-click or by user re-sizing with mouse) lower wCol
   If (wToLeft + wCol) > (w - (UBound(CD)-iCol) * m) Then
      wCol = w - wToLeft - (UBound(CD)-iCol)*m  'force column to n*cMin less right edge of LV
      For i = iCol+1 To UBound(CD) : CD(i) = cMin : Next i
      CD(iCol) = 100 * wCol / w    'set CD(iCol) - percentage of dragged or double-clicked column
      For i = iCol+1 To UBound(CD) : pToRight = pToRight + CD(i) : Next i
      CD(iCol) = 100 * wCol / w    'set CD(iCol) - percentage of dragged or double-clicked column
      '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
         For i = 1 To iCol-1  : CD(i) = CD(i) /pToLeft * (100 - CD(iCol)) : Next i   'last column only
      End If
   End If
   Tracking = 0
End Sub
'Date: 03-10-2012

created by gbSnippets