BjornA Posted May 10, 2012 Share Posted May 10, 2012 Dear All, The program below registers all files in the directory of "_New revised text" when this is on M: or N:. It then creates a database of the filenames and some other things and this works ok and is fairly fast. When I try to sort the database it doesn't however. If I am using Listview / Simplesort for a short list it works ok, but when using it for a longer list (approx 300 rows with 5 columns) it sorts very slowly, it takes just under 10 seconds to sort it. Is this normal or am I missing something? (I have tried using Autohotkey for a similar task and it sorts it almost instantenously so apparently it can be done, but I would prefer using AutoIt) expandcollapse popup; Script Start - Add your code below here #include <GUIConstantsEx.au3> #include <StructureConstants.au3> #include <ListViewConstants.au3> #include <WindowsConstants.au3> #include <Constants.au3> #include <GuiListView.au3> #include <GuiButton.au3> #include <Array.au3> Opt('MustDeclareVars', 1) global $aRec[1000][4] global $hWin, $hList, $B_DESCENDING global $CurrRec global $hBtnAccess CreateWin() Getdata() RunProgram() ;******************************************************************************************* func GetData() local $aAllDrives = DriveGetDrive("ALL") Local $search, $MyDir, $MyFile, $Au, $Size, $FullName, $Access, $FirstPos For $i = 1 to $aAllDrives[0] if StringInStr("M: N: ", $aAllDrives[$i])>0 then $search = FileFindFirstFile( $aAllDrives[$i] & "\*") if @error then exitloop while 1 $MyDir = FileFindNextFile($search) if @error then exitloop if @extended=1 then ; 1 = directory if $MyDir="_New revised text" then FileClose($search) $search=FileFindFirstFile( $aAllDrives[$i] &"\"& $MyDir & "\*.txt") while 1 $MyFile=FileFindNextFile($search) if @error then exitloop $FirstPos=StringInStr( $MyFile,"- ") if $FirstPos>1 then $Au=StringMid($MyFile,$Firstpos+2) $Au=StringMid($Au,1,StringLen($Au)-4) $Size=int(FileGetSize($aAllDrives[$i] &"\"& $MyDir &"\"& $MyFile)/1024) $FullName=$aAllDrives[$i] &"\"& $MyDir &"\"& $MyFile $Access=FileGetTime($FullName, 0, 1) GUICtrlCreateListViewItem($Au&"|"&$MyFile&"|"&$Size&"|"&$FullName&"|"&$Access,$hList) endif wend endif endif wend endif next GUISetState() Return endfunc func CreateWin() MsgBox(1,"","createwin") $hWin= GUICreate ( "Getting author name" , 500, 300, -1, -1, $WS_MINIMIZEBOX+$WS_SIZEBOX ) $hList=GUICtrlCreateListView ("Author name|File name|Size|Total name|Access", 10,10,480,250) _GUICtrlListView_SetItemCount($hList, 1005) _GUICtrlListView_SetColumnWidth($hList, 0, 130) _GUICtrlListView_SetColumnWidth($hList, 1, 270) _GUICtrlListView_SetColumnWidth($hList, 2, 50) _GUICtrlListView_SetColumnWidth($hList, 3, 50) _GUICtrlListView_SetColumnWidth($hList, 4, 100) GUICtrlSetResizing($hList,$GUI_DOCKAUTO) endfunc func RunProgram() Local $msg Global $B_DESCENDING[_GUICtrlListView_GetColumnCount($hList)] GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GuiSetState(@SW_SHOW) while 1 $msg=GUIGetMsg() if $msg = $GUI_EVENT_CLOSE Then ExitLoop wend GUIDELETE($hWin) endfunc Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ; someone else's code ! #forceref $hWnd, $iMsg, $iwParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndList, $tInfo Local $selectedRow $hWndList = $hList If Not IsHWnd($hList) Then $hWndList = GUICtrlGetHandle($hList) $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") If ($hWndFrom = $hWndList) Then If ($iCode = $LVN_COLUMNCLICK) Then $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam) _GUICtrlListView_SimpleSort($hWndList, $B_DESCENDING, DllStructGetData($tInfo, "SubItem")) ElseIf ($iCode = $NM_DBLCLK) Then $selectedRow = _GUICtrlListView_GetSelectionMark($hList) Run(@WindowsDir & "\notepad.exe " & _GUICtrlListView_GetItemText($hList, $selectedRow, 3), "") EndIf EndIf EndFunc I would be grateful for any help / Björn Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 10, 2012 Moderators Share Posted May 10, 2012 (edited) BjornA,Welcome to the AutoIt forum. Using your code, I can SimpleSort 1340 files in about 4 secs - which is considerably faster than you are managing. But in either case, I would be very wary about spending so long in a message handler - when the Help file says:"the return to the system should be as fast as possible !!!it means it! I have placed the sort outside the handler and that has dramatically improved the time taken - it now takes just over 2 secs to sort the same number of files. Look for the <<<<<<<<<<<<<<< lines - and you will have to change the drive and folder names back to match your system:expandcollapse popup; Script Start - Add your code below here #include <guiconstantsex.au3> #include <structureconstants.au3> #include <listviewconstants.au3> #include <windowsconstants.au3> #include <constants.au3> #include <guilistview.au3> #include <guibutton.au3> #include <array.au3> Opt('MustDeclareVars', 1) Global $aRec[1000][4] Global $hWin, $hList, $B_DESCENDING Global $CurrRec Global $hBtnAccess Global $iSort = -1 ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< CreateWin() Getdata() RunProgram() ;******************************************************************************************* Func GetData() Local $aAllDrives = DriveGetDrive("ALL") Local $search, $MyDir, $MyFile, $Au, $Size, $FullName, $Access, $FirstPos For $i = 1 To $aAllDrives[0] If StringInStr("M:", $aAllDrives[$i]) > 0 Then $search = FileFindFirstFile($aAllDrives[$i] & "*") If @error Then ExitLoop While 1 $MyDir = FileFindNextFile($search) If @error Then ExitLoop If @extended = 1 Then ; 1 = directory If $MyDir = "Music" Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< FileClose($search) $search = FileFindFirstFile($aAllDrives[$i] & "" & $MyDir & "*.txt") While 1 $MyFile = FileFindNextFile($search) If @error Then ExitLoop ;If $FirstPos > 1 Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< $Au = StringMid($MyFile, $FirstPos + 2) $Au = StringMid($Au, 1, StringLen($Au) - 4) $Size = Int(FileGetSize($aAllDrives[$i] & "" & $MyDir & "" & $MyFile) / 1024) $FullName = $aAllDrives[$i] & "" & $MyDir & "" & $MyFile $Access = FileGetTime($FullName, 0, 1) GUICtrlCreateListViewItem($Au & "|" & $MyFile & "|" & $Size & "|" & $FullName & "|" & $Access, $hList) ;EndIf ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< WEnd EndIf EndIf WEnd EndIf Next GUISetState() Return EndFunc ;==>GetData Func CreateWin() MsgBox(1, "", "createwin") $hWin = GUICreate("Getting author name", 500, 300, -1, -1, $WS_MINIMIZEBOX + $WS_SIZEBOX) $hList = GUICtrlCreateListView("Author name|File name|Size|Total name|Access", 10, 10, 480, 250) _GUICtrlListView_SetItemCount($hList, 1005) _GUICtrlListView_SetColumnWidth($hList, 0, 130) _GUICtrlListView_SetColumnWidth($hList, 1, 270) _GUICtrlListView_SetColumnWidth($hList, 2, 50) _GUICtrlListView_SetColumnWidth($hList, 3, 50) _GUICtrlListView_SetColumnWidth($hList, 4, 100) GUICtrlSetResizing($hList, $GUI_DOCKAUTO) EndFunc ;==>CreateWin Func RunProgram() Local $msg Global $B_DESCENDING[_GUICtrlListView_GetColumnCount($hList)] GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") GUISetState(@SW_SHOW) While 1 $msg = GUIGetMsg() If $msg = $GUI_EVENT_CLOSE Then ExitLoop If $iSort > -1 Then ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< Local $iBegin = TimerInit() _GUICtrlListView_SimpleSort($hList, $B_DESCENDING, $iSort) ConsoleWrite(TimerDiff($iBegin) & @CRLF) $iSort = -1 EndIf ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< WEnd GUIDelete($hWin) EndFunc ;==>RunProgram Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam) ; someone else's code ! #forceref $hWnd, $iMsg, $iwParam Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndList, $tInfo Local $selectedRow $hWndList = $hList If Not IsHWnd($hList) Then $hWndList = GUICtrlGetHandle($hList) $tNMHDR = DllStructCreate($tagNMHDR, $ilParam) $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom")) $iIDFrom = DllStructGetData($tNMHDR, "IDFrom") $iCode = DllStructGetData($tNMHDR, "Code") If ($hWndFrom = $hWndList) Then If ($iCode = $LVN_COLUMNCLICK) Then $tInfo = DllStructCreate($tagNMLISTVIEW, $ilParam) $iSort = DllStructGetData($tInfo, "SubItem") ; <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ElseIf ($iCode = $NM_DBLCLK) Then $selectedRow = _GUICtrlListView_GetSelectionMark($hList) Run(@WindowsDir & "notepad.exe " & _GUICtrlListView_GetItemText($hList, $selectedRow, 3), "") EndIf EndIf EndFunc ;==>WM_NOTIFYAny help? M23Edit: Just tried it with a mere 300 files and it sorts in less than a second. Edited May 10, 2012 by Melba23 New data Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
BjornA Posted May 10, 2012 Author Share Posted May 10, 2012 Dear Melba23, Thank you for the help, that is very good news. I'm not quite sure I understand why putting it outside the message handler improves the speed of the routine though. Do you know? all the best / Björn Link to comment Share on other sites More sharing options...
Moderators Melba23 Posted May 10, 2012 Moderators Share Posted May 10, 2012 BjornA, I am afraid not. But keeping the script inside a message handler for a long period (I have found about 500ms to be a reasonable limit ) is very likely to make the system unstable and crash. So perhaps the system was trying very hard not to crash during that very long wait of 10 secs and was taking cycles away from the sort algorithm. You will have to ask someone who understands the inner workings of Windows much better than I do to get a more concrete answer. M23 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area Link to comment Share on other sites More sharing options...
BjornA Posted May 10, 2012 Author Share Posted May 10, 2012 Thank you - I think I will just file it under "would be nice to know" instead of "need to know" Björn Link to comment Share on other sites More sharing options...
Spiff59 Posted May 10, 2012 Share Posted May 10, 2012 (edited) I've always wondered why all the WM_NOTIFY examples (going way back) always include the following: Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndList, $tInfo $hWndList = $hList ; <-- reference to an external Control ID If Not IsHWnd($hList) Then $hWndList = GUICtrlGetHandle($hList) ; <-- always true $hList will be a Control ID throughout the program run, so assigning it to another variable, then testing if that is a handle, and then retrieving the actual handle and reassigning the variable seems a lot of extra gyrations, particularily since WM_NOTIFY is triggered a bazillion times by a number of internal Windows events. I've been moving the ListView handle ($hWndList in this case) to be a global at the top of the script, calling the GUICtrlGetHandle() immediately after the GUICreateListView() and have yanked the 2nd and 3rd lines (above) out my WM_NOTIFY routines. Has worked fine for me. PS - Pardon me, BjornA, for inserting a marginally off-topic (but still related) post into your thread. Welcome to the forum! Edited May 10, 2012 by Spiff59 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now