Code:
'¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' FileFind v2 - fast recursive file searching. ' Public Domain code for PB/DLL 6.0 and 6.1 by Borje Hagsten ' Please read comments about changes at bottom of this posting. ' ' First released in June 2000. Replaced with this one, August 2001. ' Improved speed and uses virtual ListView to present result. ' Note: as always with PD code - use at own responsability. ' ' The program shows how to do fast recursive file searching, plus how ' to list name, path, size and date in a virtual ListView control, from ' where a selected file's properties can be viewed via right-click, ' and a file can be opened with associated program via double-click. ' Quick sorting is done via the column headers and it also shows ' how to change text- and background color in a label. All is done ' with best speed possible in mind, to enable PB developers to "show off" ' a bit, when file search needs to be done in a program. Who needs C..? [img]http://www.powerbasic.com/support/forums/wink.gif[/img] ' ' Special credits to Roberto Valois for his excellent "Virtual ListView" ' sample, and to Fred Oxenby for PathSetDlgItemPath tip. Thanks fellows.. [img]http://www.powerbasic.com/support/forums/smile.gif[/img] '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ #COMPILE EXE '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Eliminate unnecessary macros '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ %NOANIMATE = 1 %NOBUTTON = 1 %NOCOMBO = 1 %NODATETIMEPICK = 1 %NODRAGLIST = 1 %NOEDIT = 1 %NOFLATSBAPIS = 1 %NOHEADER = 1 %NOHOTKEY = 1 %NOIMAGELIST = 1 %NOIPADDRESS = 1 %NOLIST = 1 '%NOLISTVIEW = 1 %NOMONTHCAL = 1 %NONATIVEFONTCTL = 1 %NOPAGESCROLLER = 1 %NOPROGRESS = 1 %NOREBAR = 1 %NOSTATUSBAR = 1 %NOTABCONTROL = 1 %NOTOOLBAR = 1 %NOTOOLTIPS = 1 %NOTRACKBAR = 1 %NOTREEVIEW = 1 %NOUPDOWN = 1 #INCLUDE "WIN32API.INC" #INCLUDE "COMMCTRL.INC" %IDBTNPATH = 11 %IDBTNFIND = 12 %IDBTNHELP = 13 %ID_LISTVIEW = 20 %IDLABEL1 = 30 %IDLABEL2 = 31 %IDLABEL3 = 32 %IDLABEL5 = 35 %IDLABEL6 = 36 %IDLABEL7 = 37 %IDLABEL8 = 38 %IDLABEL9 = 39 %IDCOMBO1 = 40 %IDCHECK = 50 GLOBAL FileCount AS LONG, SubDirs AS LONG, Abort AS BYTE GLOBAL hDlg AS LONG, hListView AS LONG, lvSort AS LONG GLOBAL tSize AS QUAD ' For calculating the files total size GLOBAL fName AS STRING, StartPath AS STRING GLOBAL Files() AS STRING DECLARE CALLBACK FUNCTION DlgCallback() DECLARE FUNCTION GetFileDateTime(dt AS FILETIME) AS STRING DECLARE FUNCTION ShowProperties(FullFileName AS ASCIIZ, hWnd AS LONG) AS LONG DECLARE SUB NewEvents DECLARE SUB ReadDirs(BYVAL path AS STRING) DECLARE SUB SortColumn(Byval clmn AS LONG) DECLARE SUB StartAction 'PathSetDlgItemPath formats very long paths so they fit in a label, etc. DECLARE FUNCTION PathSetDlgItemPath LIB "Shlwapi.dll" _ ALIAS "PathSetDlgItemPathA"( BYVAL hDlg as long, _ 'parent's handle BYVAL wID as long, _ 'control id pszPath AS ASCIIZ) AS LONG 'ptr to text '-------------------------------------------- ' Declares for the "Browse for Folder" dialog. ' Commented out since they now exist in latest ' PB include files. Activate if compiler complains.. '-------------------------------------------- '%BIF_RETURNONLYFSDIRS = &H0001 '%BIF_DONTGOBELOWDOMAIN = &H0002 '%BIF_STATUSTEXT = &H0004 '%BIF_RETURNFSANCESTORS = &H0008 '%BIF_BROWSEFORCOMPUTER = &H1000 '%BIF_BROWSEFORPRINTER = &H2000 'TYPE BrowseInfo ' hWndOwner AS LONG ' pIDLRoot AS LONG ' pszDisplayName AS LONG ' lpszTitle AS LONG ' ulFlags AS LONG ' lpfnCallback AS LONG ' lParam AS LONG ' iImage AS LONG 'END TYPE DECLARE FUNCTION GetFolder(BYVAL hWndModal AS LONG) AS STRING 'following uncommented since it now exists in latest win32api.inc 'DECLARE SUB CoTaskMemFree LIB "ole32.dll" ALIAS "CoTaskMemFree" (BYVAL pMem AS DWORD) '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Starting point - build dialog and controls '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION PBMAIN () AS LONG LOCAL x AS LONG, y AS LONG, w AS LONG, xx AS LONG, yy AS LONG StartPath = LEFT$(CURDIR$, 3) 'root dir 'Create dialog DIALOG NEW hWndMain2&, "PB FileFind",,, 398, 117, _ %WS_CAPTION OR %WS_MINIMIZEBOX OR %WS_SYSMENU, 0 TO hDlg DIALOG GET SIZE hDlg TO x, y 'We'll use this x-value to set some control's position - otherwise they may end 'up outside the dialog when large fonts, or other screen settings are used 'ADD controls CONTROL ADD LABEL, hDlg, %IDLABEL1, "", 5, 2, 325, 10 CONTROL ADD LABEL, hDlg, %IDLABEL7, "0", x-68, 2, 25, 10, %SS_RIGHT CONTROL ADD LABEL, hDlg, %IDLABEL6, " files found", x-42, 2, 40, 10 CONTROL ADD LABEL, hDlg, %IDLABEL2, "File Type:", 8, 86, 40, 12 CONTROL ADD LABEL, hDlg, %IDLABEL5, "Start from:", 8, 102, 60, 12 CONTROL ADD LABEL, hDlg, %IDLABEL3, " " & StartPath, 45, 102, 150, 10, %SS_SUNKEN LOCAL aStr AS STRING, bStr AS STRING aStr = "PowerBasic FileFind" & $CR bStr = "Public Domain sample by" & $CR bStr = bStr & "Borje Hagsten, August 2001" w = x - 307 CONTROL ADD LABEL, hDlg, -1, "", 298, 86, w, 27, %SS_GRAYRECT CONTROL ADD LABEL, hDlg, %IDLABEL8, aStr, 296, 84, w + 1, 28, %WS_BORDER OR %SS_CENTER CONTROL ADD LABEL, hDlg, %IDLABEL9, bStr, 298, 93, w - 3, 18, %SS_CENTER DIM lst(7) AS STRING lst(0) = "*.*" : lst(1) = "*.BAS" : lst(2) = "*.BAT" : lst(3) = "*.INC" lst(4) = "*.PBR" : lst(5) = "*.RC" : lst(6) = "*.RES" : lst(7) = "*.TXT" CONTROL ADD COMBOBOX, hDlg, %IDCOMBO1, lst() , 45, 84, 60, 120 CONTROL ADD CHECKBOX, hDlg, %IDCHECK, "&Include sub-folders ", 115, 85, 80, 12 CONTROL SET CHECK hDlg, %IDCHECK, 1 CONTROL ADD BUTTON, hDlg, %IDBTNFIND, "&Search", 204, 84, 42, 14 CONTROL ADD BUTTON, hDlg, %IDBTNPATH, " &Browse...", 204, 99, 42, 14 CONTROL ADD BUTTON, hDlg, %IDBTNHELP, "&Help", 248, 84, 42, 14 CONTROL ADD BUTTON, hDlg, %IDCANCEL, "E&xit", 248, 99, 42, 14 COMBOBOX SELECT hDlg, %IDCOMBO1, 8 COMBOBOX GET TEXT hDlg, %IDCOMBO1 TO fName '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Initialize ListView control '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOCAL iccex AS INIT_COMMON_CONTROLSEX iccex.dwSize = SIZEOF(iccex) iccex.dwICC = %ICC_LISTVIEW_CLASSES CALL InitCommonControlsEx(iccex) '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Build and setup ListView control '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOCAL Style AS LONG Style = %WS_CHILD OR %WS_VISIBLE OR %WS_TABSTOP OR %LVS_REPORT OR _ %LVS_SHOWSELALWAYS OR %LVS_SINGLESEL OR %LVS_OWNERDATA CONTROL ADD "SysListView32", hDlg, %ID_LISTVIEW,"", 4, 12, x& - 12, 66, Style, _ %WS_EX_CLIENTEDGE CALL DlgCallback CONTROL HANDLE hDlg,%ID_LISTVIEW TO hListView Style = SendMessage (hListView,%LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0) Style = Style OR %LVS_EX_FULLROWSELECT OR %LVS_EX_INFOTIP OR %LVS_EX_GRIDLINES SendMessage hListView, %LVM_SETEXTENDEDLISTVIEWSTYLE, 0, BYVAL Style '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Setup 4 ListView columns '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ LOCAL LVC AS LV_COLUMN LOCAL zText AS ASCIIZ * 256 CONTROL GET SIZE hDlg, %ID_LISTVIEW TO x, y DIALOG UNITS hDlg, x, y TO PIXELS xx, yy xx = xx - 4 - GetSystemMetrics(%SM_CXVSCROLL) 'adjust for vertical scrollbar LVC.mask = %LVCF_FMT OR %LVCF_TEXT OR %LVCF_WIDTH OR %LVCF_SUBITEM zText = "Name" LVC.pszText = VARPTR(zText) LVC.fmt = %LVCFMT_LEFT LVC.cx = xx * 0.25 '25% of total width.. LVC.iOrder = 0 CONTROL SEND hDlg,%ID_LISTVIEW, %LVM_INSERTCOLUMN, 0, VARPTR(LVC) zText = "In folder" LVC.pszText = VARPTR(zText) LVC.fmt = %LVCFMT_LEFT LVC.cx = xx * 0.40 LVC.iOrder = 1 CONTROL SEND hDlg,%ID_LISTVIEW, %LVM_INSERTCOLUMN, 1, VARPTR(LVC) zText = "Size" LVC.pszText = VARPTR(zText) LVC.fmt = %LVCFMT_RIGHT LVC.cx = xx * 0.15 LVC.iOrder = 2 CONTROL SEND hDlg,%ID_LISTVIEW, %LVM_INSERTCOLUMN, 2, VARPTR(LVC) zText = "Modified" LVC.pszText = VARPTR(zText) LVC.fmt = %LVCFMT_CENTER LVC.cx = xx * 0.20 LVC.iOrder = 3 CONTROL SEND hDlg,%ID_LISTVIEW, %LVM_INSERTCOLUMN, 3, VARPTR(LVC) DIALOG SHOW MODAL hDlg CALL DlgCallback END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Main callback procedure for the dialog '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ CALLBACK FUNCTION DlgCallback() SELECT CASE CBMSG CASE %WM_INITDIALOG STATIC hBrushYellow AS LONG hBrushYellow = CreateSolidBrush(RGB(255, 255, 223)) 'light yellow for some labels CASE %WM_NCACTIVATE 'on return from other programs IF CBWPARAM THEN IF SendMessage(hListView, %LVM_GETITEMCOUNT, 0, 0) THEN 'if listview has items CONTROL SET FOCUS CBHNDL, %ID_LISTVIEW 'set focus to listview ELSE CONTROL SET FOCUS CBHNDL, %IDBTNFIND 'else set focus to Search button END IF END IF CASE %WM_CTLCOLORSTATIC SELECT CASE GetDlgCtrlID(CBLPARAM) CASE %IDLABEL8 SetBkMode CBWPARAM, %TRANSPARENT SetTextColor CBWPARAM, RGB(128, 0, 0) 'Red text color FUNCTION = hBrushYellow 'The label's background CASE %IDLABEL3, %IDLABEL9 SetBkMode CBWPARAM, %TRANSPARENT FUNCTION = hBrushYellow 'The label's background END SELECT CASE %WM_DESTROY 'Destroy what we created to avoid memory leaks Abort = 1 IF hBrushYellow THEN DeleteObject hBrushYellow PostQuitMessage 0 CASE %WM_COMMAND SELECT CASE CBCTL CASE %IDBTNFIND : StartAction 'Start a file search procedure CASE %IDCANCEL : DIALOG END CBHNDL 'Exit CASE %IDBTNPATH IF LEN(GetFolder(CBHNDL)) THEN 'PathSetDlgItemPath formats very long paths so they fit in label CALL PathSetDlgItemPath(CBHNDL,%IDLABEL3, BYVAL STRPTR(StartPath)) END IF CASE %IDBTNHELP LOCAL txt AS STRING txt = "Right-click on search results for file properties." + $CRLF + _ "Double-click on search results for viewing file." + $CRLF + _ "Sort columns by clicking on the ListView headers." + CHR$(0) CALL MessageBox(CBHNDL, BYVAL STRPTR(txt), _ "Crappy help.." & CHR$(0), %MB_ICONASTERISK) END SELECT CASE %WM_NOTIFY IF LOWRD(CBWPARAM) = %ID_LISTVIEW THEN LOCAL bPath AS ASCIIZ * %MAX_PATH, bName AS ASCIIZ * 300 LOCAL nmLvPtr AS NM_LISTVIEW PTR, lvDinfoPtr As LV_DISPINFO Ptr nmLvPtr = CBLPARAM SELECT CASE @nmLvPtr.hdr.code Case %LVN_GETDISPINFO 'Virtual ListView asks for Item text lvDinfoPtr = CBLPARAM If (@lvDinfoPtr.item.mask And %LVIF_TEXT) Then bName = PARSE$(Files(@lvDinfoPtr.item.iItem), $TAB, _ @lvDinfoPtr.item.iSubItem + 1) @lvDinfoPtr.item.pszText = VarPtr(bName) End If CASE %LVN_COLUMNCLICK 'If click on column header IF @nmLvPtr.iSubItem <> -1 THEN SortColumn @nmLvPtr.iSubItem + 1 END IF CASE %NM_RCLICK 'If Right-click in list, IF @nmLvPtr.iItem > -1 THEN 'view file properties CALL ListView_GetItemText(hListView, @nmLvPtr.iItem, 1, bPath, 255) CALL ListView_GetItemText(hListView, @nmLvPtr.iItem, 0, bName, 255) ShowProperties bPath & bName, CBHNDL END IF CASE %NM_DBLCLK 'If Double-click in list IF @nmLvPtr.iItem > -1 THEN 'view file CALL ListView_GetItemText(hListView, @nmLvPtr.iItem, 1, bPath, 255) CALL ListView_GetItemText(hListView, @nmLvPtr.iItem, 0, bName, 255) ShellExecute 0, "open", bPath & bName, "", "", %SW_SHOW END IF END SELECT END IF END SELECT END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Start and end point of a file search action '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ SUB StartAction LOCAL btnText AS STRING DIALOG DOEVENTS CONTROL GET TEXT hDlg, %IDBTNFIND TO btnText IF btnText = "&Cancel" THEN IF MessageBox(hDlg, "Abort the search?" & CHR$(0),"PB FindFile" _ & CHR$(0), 36) = 6 THEN Abort = 1 DIALOG DOEVENTS ELSE LOCAL t AS SINGLE t = TIMER: Abort = 0 : FileCount = 0 : REDIM Files(0) 'initiate these ListView_SetItemCountEx hListView, FileCount, 0 'clear virtual ListView CONTROL SET TEXT hDlg, %IDLABEL7, "0" 'zero files found.. CONTROL GET TEXT hDlg, %IDCOMBO1 TO fName 'get type of file to search for CONTROL GET CHECK hDlg, %IDCHECK TO SubDirs 'if to include sub-dirs in search EnableMenuItem GetSystemMenu(hDlg, 0), %SC_CLOSE, %MF_GRAYED 'disable system menu's close CONTROL SET TEXT hDlg, %IDBTNFIND, "&Cancel" 'also acts as Cancel-button.. CONTROL DISABLE hDlg, %IDCANCEL 'disable controls CONTROL DISABLE hDlg, %IDBTNHELP CONTROL DISABLE hDlg, %IDBTNPATH CONTROL DISABLE hDlg, %IDCOMBO1 CONTROL DISABLE hDlg, %IDCHECK DIALOG DOEVENTS tSize = 0 'reset total file size counter IF ASC(StartPath, -1) <> 92 THEN StartPath = StartPath & "\" 'make sure path ends with backslash CALL ReadDirs(StartPath) 'call main search procedure REDIM PRESERVE Files(FileCount - 1) 'adjust array ListView_SetItemCountEx hListView, FileCount, %LVSICF_NOINVALIDATEALL '<- NOTE! CONTROL SET TEXT hDlg, %IDLABEL7, FORMAT$(FileCount) 'and show proper result t = TIMER - t 'the time it took text$ = STR$(FileCount) & " " & fName & " in " & FORMAT$(t, "0.000") & " sec." text$ = text$ & " with a total size of " & FORMAT$(tSize, "#,###") & " bytes." CONTROL SET TEXT hDlg, %IDLABEL1, "Found: " & text$ CONTROL SET TEXT hDlg, %IDBTNFIND, "&Search" 'make it search-button again CONTROL ENABLE hDlg, %IDCANCEL 'enable controls CONTROL ENABLE hDlg, %IDBTNHELP CONTROL ENABLE hDlg, %IDBTNPATH CONTROL ENABLE hDlg, %IDCOMBO1 CONTROL ENABLE hDlg, %IDCHECK EnableMenuItem GetSystemMenu(hDlg, 0), %SC_CLOSE, %MF_ENABLED 'enable system menu's close DIALOG DOEVENTS END IF END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Recursive file search procedure '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ SUB ReadDirs(BYVAL path AS STRING) LOCAL hSearch AS DWORD 'search handle LOCAL tmpSize AS QUAD 'must use QUAD, in case of huge files.. LOCAL WFD AS WIN32_FIND_DATA 'FindFirstFile structure LOCAL curpath AS ASCIIZ * %MAX_PATH 'what to search for IF TALLY(path, "\") < 4 THEN CONTROL SET TEXT hDlg, %IDLABEL1, "Searching: " & path & ".." END IF curpath = path & fName 'this is what we want to find hSearch = FindFirstFile(curpath, WFD) 'get search handle, if success - IF hSearch <> %INVALID_HANDLE_VALUE THEN 'loop through directory for files DO IF (WFD.dwFileAttributes AND %FILE_ATTRIBUTE_DIRECTORY) _ ' if not directory bit (16) is set <> %FILE_ATTRIBUTE_DIRECTORY THEN ' (files only here..) NewEvents 'take a breath.. IF Abort = 1 THEN EXIT DO '------------------------------------------------------------------ ' Store the info in tab-delimited array, for list view control. ' This is where you can use these data for filtering (IF/THEN) and/or ' also add a function for searching the found file for a string, etc. '------------------------------------------------------------------ tmpSize = WFD.nFileSizeHigh * (%MAXDWORD + 1) + WFD.nFileSizeLow tSize = tSize + tmpSize IF FileCount MOD 200 = 0 THEN REDIM PRESERVE Files(FileCount + 200) Files(FileCount) = WFD.cFileName & $TAB & Path & $TAB & _ FORMAT$(tmpSize, "* #######,") & $TAB & _ GetFileDateTime(WFD.ftLastWriteTime) INCR FileCount '<- NOTE! IF FileCount < 20 THEN 'while less than 20 found, update every time ListView_SetItemCountEx hListView, FileCount, %LVSICF_NOINVALIDATEALL CONTROL SET TEXT hDlg, %IDLABEL7, FORMAT$(FileCount) ELSE IF FileCount MOD 10 = 0 THEN 'if extensive search, update every 10th for better speed ListView_SetItemCountEx hListView, FileCount, %LVSICF_NOINVALIDATEALL CONTROL SET TEXT hDlg, %IDLABEL7, FORMAT$(FileCount) END IF END IF END IF LOOP WHILE FindNextFile(hSearch, WFD) CALL FindClose(hSearch) END IF IF SubDirs THEN 'if to search in subdirectories. curpath = path & "*" hSearch = FindFirstFile(curpath, WFD) IF hSearch <> %INVALID_HANDLE_VALUE THEN DO IF (WFD.dwFileAttributes AND %FILE_ATTRIBUTE_DIRECTORY) THEN 'if directory bit (16) is set IF (ASC(WFD.cFileName) = 46) = 0 THEN 'Not . or .. NewEvents IF Abort = 1 THEN EXIT DO 'now we have a subdir, call function again to find eventual files '(each recursive call gets its own place on the stack..) CALL ReadDirs(path & RTRIM$(WFD.cFileName, CHR$(0)) & "\") END IF END IF LOOP WHILE FindNextFile(hSearch, WFD) CALL FindClose(hSearch) END IF END IF END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Custom-built DoEvents for faster action.. '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ SUB NewEvents LOCAL Msg AS tagMsg WHILE PeekMessage(Msg, %NULL, %NULL, %NULL, %PM_REMOVE) IF IsDialogMessage(hDlg, Msg) THEN ELSE TranslateMessage Msg DispatchMessage Msg END IF Wend END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Sort Files array and update ListView '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ SUB SortColumn(Byval clmn AS LONG) LOCAL I AS LONG lvSort = NOT lvSort 'toggle direction flag REDIM dummy(UBOUND(files)) AS STRING 'use temporary array for sorting FOR I = 0 TO UBOUND(Files) 'parse out proper "column" to temp. array dummy(I) = PARSE$(Files(I), $TAB, clmn) NEXT IF lvSort THEN ARRAY SORT dummy(), COLLATE UCASE, TAGARRAY Files(), DESCEND 'sort temp arr, tag original ELSE ARRAY SORT dummy(), COLLATE UCASE, TAGARRAY Files(), ASCEND END IF InvalidateRect hListView, BYVAL %NULL, 0 : UpDateWindow hListView 'redraw listview END SUB '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Return proper file date and time as string '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION GetFileDateTime(dt AS FILETIME) AS STRING LOCAL lpsystime AS SYSTEMTIME LOCAL sDate AS ASCIIZ * 64 'date buffer - %LDT_SIZE = 64 LOCAL sTime AS ASCIIZ * 64 'time buffer - %LDT_SIZE = 64 'set the last modified date & time and the get the correct formats CALL FileTimeToLocalFileTime(dt, dt) CALL FileTimeToSystemTime(dt, lpsystime) CALL GetDateFormat (%LOCALE_USER_DEFAULT, %DATE_SHORTDATE, BYVAL VARPTR(lpsystime), _ BYVAL %NULL, sDate, 64) CALL GetTimeFormat (%LOCALE_USER_DEFAULT, %TIME_FORCE24HOURFORMAT OR %TIME_NOSECONDS, _ BYVAL VARPTR(lpsystime), BYVAL %NULL, sTime, 64) FUNCTION = sDate & " " & sTime END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Browse for new start-folder '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION GetFolder(BYVAL hParent AS LONG) AS STRING LOCAL PathID AS LONG, bInf AS BROWSEINFO, zPath AS ASCIIZ * %MAX_PATH bInf.hWndOwner = hParent 'Set some properties for the folder dialog bInf.ulFlags = %BIF_RETURNONLYFSDIRS OR %BIF_DONTGOBELOWDOMAIN bInf.lpszTitle = VARPTR(zPath) PathID = SHBrowseForFolder(bInf) 'Show the Browse-For-Folder dialog IF PathID THEN IF SHGetPathFromIDList(BYVAL PathID, zPath) THEN StartPath = RTRIM$(zPath, CHR$(0)) FUNCTION = StartPath END IF END IF CoTaskMemFree PathID 'Free allocated memory END FUNCTION '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ ' Show Windows property page for a file '¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤¤ FUNCTION ShowProperties(FullFileName AS ASCIIZ, hWnd AS LONG) AS LONG LOCAL SHEI AS SHELLEXECUTEINFO LOCAL lRes AS LONG, lpVerb AS ASCIIZ * 255 SHEI.cbSize = LEN(SHEI) SHEI.fMask = %SEE_MASK_NOCLOSEPROCESS OR %SEE_MASK_INVOKEIDLIST OR %SEE_MASK_FLAG_NO_UI SHEI.hwnd = hWnd lpVerb = "properties" SHEI.lpVerb = VARPTR(lpVerb) SHEI.lpFile = VARPTR(FullFileName) SHEI.lpParameters = %NULL SHEI.lpDirectory = %NULL SHEI.nShow = 0 SHEI.hInstApp = 0 SHEI.lpIDList = 0 lRes = ShellExecuteEX(SHEI) FUNCTION = SHEI.hInstApp END FUNCTION
Corrected code: In ReadDirs, moved INCR FileCount up before IF/THEN block.
In StartAction, added ListView_SetItemCountEx after REDIM Files().
January 30, 2002 - adjusted code to work with both 6.0 and 6.1. Changed
FindFile return variable to DWORD, commented out BFF declares and changed
FORMAT$ in ReadDirs routine to more correct format.
[This message has been edited by Borje Hagsten (edited February 16, 2002).]
Comment