taurus905 Posted June 20, 2022 Share Posted June 20, 2022 Hello All, I use _ArrayDisplay a lot because it's so convenient. I'd like some input on how to have it timeout and close without the need to click. I'm sure this is very easy for some people here, but the solution eludes me. Thank you in advance for any direction. taurus905 Func _ArrayDisplay(Const ByRef $aArray, $sTitle = Default, $sArrayRange = Default, $iFlags = Default, $vUser_Separator = Default, $sHeader = Default, $iMax_ColWidth = Default) #forceref $vUser_Separator Local $iRet = __ArrayDisplay_Share($aArray, $sTitle, $sArrayRange, $iFlags, Default, $sHeader, $iMax_ColWidth, 0, False) Return SetError(@error, @extended, $iRet) EndFunc ;==>_ArrayDisplay "Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs Link to comment Share on other sites More sharing options...
Nine Posted June 20, 2022 Share Posted June 20, 2022 The easiest way in my opinion is to create another process responsible to close the arraydisplay after a specified delay : #pragma compile(AutoItExecuteAllowed, true) #include <Constants.au3> #include <Array.au3> #include <WinAPIFiles.au3> Opt ("MustDeclareVars", True) Local $aVar = [1,2,3,4,5,6,7,8] Local $sTitle = "My Array Display Title" _CreateChild($sTitle, 5000) _ArrayDisplay($aVar, $sTitle) Func _CreateChild ($sTitle, $iDuration) Local $sTempFile = _WinAPI_GetTempFileName (@TempDir, "~") Local $sScript = _ "#NoTrayIcon" & @CRLF & _ "While Sleep(100)" & @CRLF & _ "If WinExists('" & $sTitle & "') Then ExitLoop" & @CRLF & _ "WEnd" & @CRLF & _ "Sleep(" & $iDuration & ")" & @CRLF & _ "If WinExists('" & $sTitle & "') Then WinClose('" & $sTitle & "')" & @CRLF & _ "Sleep(200)" & @CRLF & _ "FileDelete (@ScriptFullPath)" FileWrite ($sTempFile, $sScript) Run (@AutoItExe & ' /AutoIt3ExecuteScript "' & $sTempFile & '"', @TempDir, @SW_HIDE) EndFunc “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
taurus905 Posted June 20, 2022 Author Share Posted June 20, 2022 4 minutes ago, Nine said: The easiest way in my opinion is to create another process responsible to close the arraydisplay after a specified delay : Thank you, Nine. That's a very elegant solution. I love to learn new ways to use AutoIt (my favorite for creating tools). taurus905 "Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs Link to comment Share on other sites More sharing options...
Nine Posted June 20, 2022 Share Posted June 20, 2022 Glad you like it “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
pixelsearch Posted June 20, 2022 Share Posted June 20, 2022 (edited) Hi taurus905 & Nine : I always liked the AdlibRegister way, which calls the Adlib function only once (maximum) in OP's case, for example : #include <Array.au3> Local $aVar = [0,1,2,3,4,5,6,7,8,9] Local $iTimeOut = 5 ; <=== 5s, change to your wish Global $g_sTitle = "Close in " & $iTimeOut & "s" AdlibRegister("MyAdLibFunc", $iTimeOut * 1000) _ArrayDisplay($aVar, $g_sTitle) AdlibUnRegister("MyAdLibFunc") ; ...script continuation here Func MyAdLibFunc() If WinExists($g_sTitle) Then AdlibUnRegister("MyAdLibFunc") WinClose($g_sTitle) EndIf EndFunc ;==>MyAdLibFunc But I don't know if it's a good idea to close automatically the new version of ArrayDisplay after a timeout without exiting AutoIt, as the script continues. What about the eventual big global arrays $_g_ArrayDisplay_aIndex and $_g_ArrayDisplay_aIndexes which could still use a lot of memory ? And the subclassing in ArrayDisplay not being removed, no problem with that ? IDK Edit: the Adlib function could even be shorter in OP's case, something like this : Func MyAdLibFunc() AdlibUnRegister("MyAdLibFunc") WinClose($g_sTitle) EndFunc ;==>MyAdLibFunc Edited June 20, 2022 by pixelsearch Link to comment Share on other sites More sharing options...
taurus905 Posted June 20, 2022 Author Share Posted June 20, 2022 6 minutes ago, pixelsearch said: But I don't know if it's a good idea to close automatically the new version of ArrayDisplay after a timeout without exiting AutoIt, as the script continues. Hello pixelsearch, Your input is always welcomed. In fact, in many cases I want the AutoIt script to continue. I will test Nine's solution and yours to see which works best for the particular instance. I appreciate both of your ideas, since I love to have options. taurus905 "Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs Link to comment Share on other sites More sharing options...
pixelsearch Posted June 20, 2022 Share Posted June 20, 2022 Always a pleasure to help you Link to comment Share on other sites More sharing options...
Nine Posted June 20, 2022 Share Posted June 20, 2022 @pixelsearch I like your solution, but I have found that in some situations (when the function is truly blocking), the adlib approach (or other timer) will not work. So this is why I always favor the second-process approach, which will work all the time. Just my 2 cents BTW. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
pixelsearch Posted June 20, 2022 Share Posted June 20, 2022 Hi Nine Thanks for your input. I did some tests in 2019 and kept them in a script, so I'll post it now 3 years after, without changing a line in it. I don't feel like running it again or re-testing but I never considered ArrayDisplay as a blocking function. The AdLib way coupled with ArrayDisplay has been used nearly daily since 2019 by a person I sent a script to, and he never reported something strange happened, maybe he was lucky expandcollapse popup#include <Array.au3> #include <MsgBoxConstants.au3> Opt("WinTitleMatchMode", -2) ;1=start, 2=subStr, 3=exact, 4=advanced, -1 to -4=Nocase If ProcessExists("SciTE.exe") = 0 Then MsgBox($MB_SYSTEMMODAL, "", "You will need SciTE.exe to be running for ConsoleWrite to display.") EndIf Example() Func Example() ; Register the function MyAdLibFunc() to be called every 250ms (default). AdlibRegister("MyAdLibFunc") ; Sleep does not stop AdLib functions from running. Sleep(1000) ; ============================================================================================================================== ; Help file : "AdLib functions don't run while a blocking function is shown e.g. MsgBox, InputBox, WinWait, WinWaitClose etc..." ; ============================================================================================================================== MsgBox($MB_SYSTEMMODAL, "", "No console message(s) will be shown whilst the messagebox is displayed.") ; ok, blocking function ; InputBox("Just a test", "Enter what you want") ; ok, blocking function ; Initiates a Browse for Folder dialog. ; $sFileSelectFolder = FileSelectFolder("Select a folder", "") ; ok, blocking function (help file, topic... HotKeySet) ; Initiates an Open File dialog. ; $sFileOpenDialog = FileOpenDialog("Select a file", @WindowsDir & "\", "All (*.*)") ; ok, blocking function ; Initiates a Save File dialog. ; $sFileSaveDialog = FileSaveDialog("Choose a filename", @WorkingDir, "Scripts (*.au3)") ; ok, blocking function ; WinWait("fghdfghj") ; NOT a blocking function (help file wrong, topics AdlibRegister & AdlibUnRegister) ; ******* ; Open WordPad before this test, then run this script without closing WordPad immediately ; WinWaitClose("WordPad") ; NOT a blocking function (help file wrong, topics AdlibRegister & AdlibUnRegister) ; ************ ; https://www.autoitscript.com/forum/topic/197449-_arraydisplay-and-msgbox-at-same-time/ ; Local $aArray[5] = [0, 1, 2, 3, 4] ; _ArrayDisplay($aArray) ; NOT a blocking function as a Mod wrote "_ArrayDisplay is a blocking function" in the precedent link ; ************* ; When needed, add functions here for testing if they are blocking functions or not ; The AdLib function MyAdLibFunc() will start again. Sleep(1000) ; Unregister the function MyAdLibFunc() from being called every 250ms. AdlibUnRegister("MyAdLibFunc") EndFunc ;==>Example Func MyAdLibFunc() ; Assign a static variable to hold the number of times the function is called. Local Static $iCount = 0 $iCount += 1 ConsoleWrite("MyAdLibFunc called " & $iCount & " time(s)" & @CRLF) EndFunc ;==>MyAdLibFunc Link to comment Share on other sites More sharing options...
taurus905 Posted June 20, 2022 Author Share Posted June 20, 2022 2 hours ago, pixelsearch said: Edit: the Adlib function could even be shorter in OP's case, something like this : @pixelsearch I was wondering why AdlibUnRegister("MyAdLibFunc") is called twice. Is there a reason, or could the first one be removed? #include <Array.au3> Local $aVar = [0,1,2,3,4,5,6,7,8,9] Local $iTimeOut = 5 ; <=== 5s, change to your wish Global $g_sTitle = "Close in " & $iTimeOut & "s" AdlibRegister("MyAdLibFunc", $iTimeOut * 1000) _ArrayDisplay($aVar, $g_sTitle) AdlibUnRegister("MyAdLibFunc") ; ...script continuation here Func MyAdLibFunc() AdlibUnRegister("MyAdLibFunc") WinClose($g_sTitle) EndFunc ;==>MyAdLibFunc "Never mistake kindness for weakness."-- Author Unknown --"The highest point to which a weak but experienced mind can rise is detecting the weakness of better men."-- Georg Lichtenberg --Simple Obfuscator (Beta not needed.), Random names for Vars and Funcs Link to comment Share on other sites More sharing options...
pixelsearch Posted June 20, 2022 Share Posted June 20, 2022 6 minutes ago, taurus905 said: ...or could the first one be removed? Yes you can remove the 1st one. The 2nd one should be enough in your case, it's shorter taurus905 1 Link to comment Share on other sites More sharing options...
jugador Posted June 21, 2022 Share Posted June 21, 2022 add timer to __ArrayDisplay_Share to auto close #include <GUIConstantsEx.au3> Example() Func Example() Local $hGUI = GUICreate("Example", 400, 400) Local $idOK = GUICtrlCreateButton("OK", 310, 370, 85, 25) GUISetState(@SW_SHOW, $hGUI) Local $iTimmer = TimerInit() ;<<=== timer While 1 If TimerDiff($iTimmer) > 3000 Then ExitLoop ;<<=== check to auto close Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idOK EndSwitch WEnd GUIDelete($hGUI) EndFunc Link to comment Share on other sites More sharing options...
mikell Posted June 21, 2022 Share Posted June 21, 2022 13 hours ago, pixelsearch said: I never considered ArrayDisplay as a blocking function. HI Could you please explain/elaborate ? ArrayDisplay (__ArrayDisplay_Share) includes a gui with an infinite While loop, and no global var inside to interact with to allow an exit from this loop Your code works (nicely indeed) using a WinClose, which is (sort of) a brute force way and not really a gentle & sweet exit/return from the func Link to comment Share on other sites More sharing options...
pixelsearch Posted June 21, 2022 Share Posted June 21, 2022 44 minutes ago, mikell said: Could you please explain/elaborate ? Hey Soulful cat @mikell it's been a long time ! imho a "blocking function" is a function that stops AdlibRegister to be called while the function is active, no more, no less. If you look at the help file example, topics AdlibRegister or AdlibUnRegister, you'll notice this important sentence written in the example : ; AdLib functions don't run while a blocking function is shown e.g. MsgBox, InputBox, WinWait, WinWaitClose etc. My tests above (from 2019) show this sentence is not true, because WinWait and WinWaitClose keep on running AdLib functions, while MsgBox and InputBox stop AdLib from running. So who wrote this sentence in the example as it's half true, half false ? It would have been a better idea to indicate somewhere a list of all the blocking functions (or in the topic of each blocking function). A non exhaustive list is : MsgBox , InputBox , FileSelectFolder [as indicated in topic... HotKeySet ! then tested in 2019] , FileOpenDialog , FileSaveDialog etc... That's the reason why I consider _ArrayDisplay "not blocking" as you can run an Adlib function while ArrayDisplay is active... no more, no less 15 hours ago, Nine said: I like your solution, but I have found that in some situations (when the function is truly blocking)... Nine expressed this in a nice way because he indicated why he always chooses "the second-process approach, which will work all the time". He knows that _ArrayDisplay isn't a "truly blocking function" (compared to MsgBox for example) and "truly" is the word ! So instead of checking each time if a function is a "truly" blocking function or not, he prefers to always use the 2nd process approach, while I prefer the simpler AdLib approach... when possible mikell 1 Link to comment Share on other sites More sharing options...
mikell Posted June 22, 2022 Share Posted June 22, 2022 Thanks for this clarification Link to comment Share on other sites More sharing options...
Nine Posted June 22, 2022 Share Posted June 22, 2022 Another reason why I prefer the second-process approach is that you can pass as many parameters as you need to without creating global variables. The adlib approach forces the creation of many globals if you intend to vary the calls. Since the best practices in programming is to reduce as much as possible the usage of global variables... “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
NassauSky Posted September 20 Share Posted September 20 2 years later... Just playing with this a little now. If I have time I'll look for another solution. @Nine I like that idea but it seems the first problem I found is it has to be run on a PC that has Autoit installed. I'd have to have the end-user install (or pre-package) the @AutoItExe package to use the specified Run() command 🙂 I like the left field/right field brain storming. Link to comment Share on other sites More sharing options...
argumentum Posted September 20 Share Posted September 20 14 minutes ago, NassauSky said: If I have time I'll look for another solution. The best solution is something along of what @jugador presented. Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. Link to comment Share on other sites More sharing options...
NassauSky Posted September 23 Share Posted September 23 (edited) Thanks @argumentum Ok I don't see a way yet of doing it using @jugador method since _ArrayDisplay is a synchronous blocking function but for now I might use @pixelsearch method as shown below but there's still a global variable $g_sTitle I'll just accept for now: #include <GUIConstantsEx.au3> #include <Array.au3> Example() Func Example() Local $hGUI = GUICreate("Example", 400, 400) Local $idOK = GUICtrlCreateButton("ArrayDisplay Timeout", 250, 370, 115, 25) GUISetState(@SW_SHOW, $hGUI) While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idOK AdlibRegister("_CloseArrayDisplay", 2500) ; Check every 500 ms Local $aArray[5] = [1, 2, 3, 4, 5] Global $g_sTitle = "Array Display" _ArrayDisplay($aArray, $g_sTitle) ; Display the array EndSwitch WEnd GUIDelete($hGUI) AdlibUnRegister("_CloseArrayDisplay") ; Stop checking when the main loop ends EndFunc Func _CloseArrayDisplay() If WinExists($g_sTitle) Then AdlibUnRegister("_CloseArrayDisplay") WinClose($g_sTitle) EndIf EndFunc Edited September 23 by NassauSky Link to comment Share on other sites More sharing options...
argumentum Posted September 23 Share Posted September 23 (edited) 2 hours ago, NassauSky said: I don't see a way yet of doing it using @jugador method These UDFs can be tweaked at will for personal use. Don't be afraid of braking anything. You can always restore the original ( if you make a copy/backup of it ). _ArrayDisplay(), if you look at the code, runs __ArrayDisplay_Share(). So you'd edit __ArrayDisplay_Share() with a global variable in "ArrayDisplayInternals.au3". Look for "If $aMsg[1] = $hGUI Then" and add your easily patchable code (TM) to it, like: If $__g_ArrayDisplay_Timeout_msExit Then If TimerDiff($hRetTimer) > $__g_ArrayDisplay_Timeout_msExit Then GUIDelete($hGUI) Exit $__g_ArrayDisplay_Timeout_ecExit EndIf EndIf If $aMsg[1] = $hGUI Then then you put those new variables on top of the script with a helper function to set them: Global $__g_ArrayDisplay_Timeout_msExit = 0 ; if timeout: EXIT Global $__g_ArrayDisplay_Timeout_ecExit = 99 ; if timeout exit: show this @ExitCode Func _DebugArrayDisplay_TimeoutExit($mSec = Default, $iExitCode = Default) If $mSec <> Default Then $__g_ArrayDisplay_Timeout_msExit = $mSec If $iExitCode <> Default Then $__g_ArrayDisplay_Timeout_ecExit = $iExitCode Return SetError(0, $__g_ArrayDisplay_Timeout_ecExit, $__g_ArrayDisplay_Timeout_msExit) EndFunc ;==>_DebugArrayDisplay_TimeoutExit That way you can call your helper function _DebugArrayDisplay_TimeoutExit() to setup your timeout, then after that call _ArrayDisplay() ,,,now that I look at it looks intimidating. But we learn by doing so, go at it. Is just code. Might as well give you the ArrayDisplayInternals.au3 I use Spoiler expandcollapse popup#include-once #include "AutoItConstants.au3" #include "MsgBoxConstants.au3" #include "StringConstants.au3" #include <GUIConstantsEx.au3>; added For __ArrayDisplay_SubItemHitTest_ClipPut #include <GuiListView.au3>; added For __ArrayDisplay_SubItemHitTest_ClipPut ; #INDEX# ======================================================================================================================= ; Title .........: Internal UDF Library for AutoIt3 _ArrayDisplay() and _DebugArrayDisplay() ; AutoIt Version : 3.3.16.1 ;;; https://www.autoitscript.com/forum/topic/196962-suggested-modification-to-arraydisplayinternalsau3/?do=findComment&comment=1507661 ; Description ...: Internal functions for the Array.au3 and Debug.au3 ; Author(s) .....: Melba23, jpm, LarsJ, pixelsearch ; Modifier(s) ...: Tippex ; https://www.autoitscript.com/forum/topic/196962-suggested-modification-to-arraydisplayinternalsau3/ ; : argumentum ; =============================================================================================================================== #Region Global Variables and Constants ; #VARIABLES# =================================================================================================================== ; for use with the notify handler Global $_g_ArrayDisplay_bUserFunc = False Global $_g_ArrayDisplay_hListView Global $_g_ArrayDisplay_iTranspose Global $_g_ArrayDisplay_iDisplayRow Global $_g_ArrayDisplay_aArray Global $_g_ArrayDisplay_iDims Global $_g_ArrayDisplay_nRows Global $_g_ArrayDisplay_nCols Global $_g_ArrayDisplay_iItem_Start Global $_g_ArrayDisplay_iItem_End Global $_g_ArrayDisplay_iSubItem_Start Global $_g_ArrayDisplay_iSubItem_End Global $_g_ArrayDisplay_aIndex Global $_g_ArrayDisplay_aIndexes[1] Global $_g_ArrayDisplay_iSortDir Global $_g_ArrayDisplay_asHeader Global $_g_ArrayDisplay_aNumericSort Global $ARRAYDISPLAY_ROWPREFIX = "#" Global $ARRAYDISPLAY_NUMERICSORT = "*" ; =============================================================================================================================== ; #CONSTANTS# =================================================================================================================== Global Const $ARRAYDISPLAY_COLALIGNLEFT = 0 ; (default) Column text alignment - left Global Const $ARRAYDISPLAY_TRANSPOSE = 1 ; Transposes the array (2D only) Global Const $ARRAYDISPLAY_COLALIGNRIGHT = 2 ; Column text alignment - right Global Const $ARRAYDISPLAY_COLALIGNCENTER = 4 ; Column text alignment - center Global Const $ARRAYDISPLAY_VERBOSE = 8 ; Verbose - display MsgBox on error and splash screens during processing of large arrays Global Const $ARRAYDISPLAY_ONLYCOPYBUTTONS = 16 ; Only 'Copy' buttons displayed Global Const $ARRAYDISPLAY_NOBUTTONSDISPLAY = 32 ; No buttons displayed Global Const $ARRAYDISPLAY_NOROW = 64 ; No 'Row' column displayed Global Const $ARRAYDISPLAY_CHECKERROR = 128 ; return if @error <> 0 (avoid display after _Array*() errors) Global Const $ARRAYDISPLAY_NODATALABELDISPLAY = 256 ; 128 ; No data label displayed Global Const $ARRAYDISPLAY_NoRightClick = 512 Global Const $_ARRAYCONSTANT_tagLVITEM = "struct;uint Mask;int Item;int SubItem;uint State;uint StateMask;ptr Text;int TextMax;int Image;lparam Param;" & _ "int Indent;int GroupID;uint Columns;ptr pColumns;ptr piColFmt;int iGroup;endstruct" ; =============================================================================================================================== #EndRegion Global Variables and Constants #Region Functions list ; #CURRENT# ===================================================================================================================== ; =============================================================================================================================== ; #INTERNAL_USE_ONLY# =========================================================================================================== ; __ArrayDisplay_Share ; __ArrayDisplay_SortIndexes ; ___ArrayDisplay_NotifyHandler ; __ArrayDisplay_GetSortColStruct ; __ArrayDisplay_SortArrayStruct ; __ArrayDisplay_Transpose ; __ArrayDisplay_HeaderSetItemFormat ; __ArrayDisplay_GetItemText ; __ArrayDisplay_GetItemTextStringSelected ; __ArrayDisplay_JustifyColumn ; =============================================================================================================================== #EndRegion Functions list Global $__g_ArrayDisplay_Timeout_msReturn = 0 ; if timeout: close the gui Func _DebugArrayDisplay_TimeoutReturn($mSec = Default) If $mSec <> Default Then $__g_ArrayDisplay_Timeout_msReturn = $mSec Return $__g_ArrayDisplay_Timeout_msReturn EndFunc ;==>_DebugArrayDisplay_DefaultFlags Global $__g_ArrayDisplay_Timeout_msExit = 0 ; if timeout: EXIT Global $__g_ArrayDisplay_Timeout_ecExit = 99 ; if timeout exit: show this @ExitCode Func _DebugArrayDisplay_TimeoutExit($mSec = Default, $iExitCode = Default) If $mSec <> Default Then $__g_ArrayDisplay_Timeout_msExit = $mSec If $iExitCode <> Default Then $__g_ArrayDisplay_Timeout_ecExit = $iExitCode Return SetError(0, $__g_ArrayDisplay_Timeout_ecExit, $__g_ArrayDisplay_Timeout_msExit) EndFunc ;==>_DebugArrayDisplay_TimeoutExit Global $__g_ArrayDisplay_Share_iFlags = 0 Func _DebugArrayDisplay_DefaultFlags($iFlags = Default) If $iFlags <> Default Then $__g_ArrayDisplay_Share_iFlags = $iFlags Return $__g_ArrayDisplay_Share_iFlags EndFunc ;==>_DebugArrayDisplay_DefaultFlags Func __ArrayDisplay_SubItemHitTest_ClipPut($hWnd, $iX = -1, $iY = -1) $hWnd = GUICtrlGetHandle($hWnd) Local $_mPos = MouseGetPos(), $aTest = _GUICtrlListView_SubItemHitTest($hWnd, $iX, $iY) ReDim $aTest[12] $aTest[11] = _GUICtrlListView_GetItemText($hWnd, $aTest[0], $aTest[1]) ClipPut($aTest[11]) ToolTip($aTest[11], $_mPos[0] - 20, $_mPos[1] - 60, "ClipPut", 0, 4) AdlibRegister("__ArrayDisplay_ToolTipOff", 500) Return $aTest EndFunc ;==>__ArrayDisplay_SubItemHitTest_ClipPut Func __ArrayDisplay_ToolTipOff() AdlibUnRegister("__ArrayDisplay_ToolTipOff") ToolTip("") EndFunc ;==>__ArrayDisplay_ToolTipOff Func __ArrayDisplay_Share(Const ByRef $aArray, $sTitle = Default, $sArrayRange = Default, $iFlags = Default, $vUser_Separator = Default, $sHeader = Default, $iDesired_Colwidth = Default, $hUser_Function = Default, $bDebug = True, Const $_iScriptLineNumber = @ScriptLineNumber, Const $_iCallerError = @error, Const $_iCallerExtended = @extended) Local $hRetTimer = TimerInit(), $sMsgBoxTitle = (($bDebug) ? ("_DebugArrayDisplay") : ("_ArrayDisplay")) ; to avoid user_function using _DebugAArrayDislay() recursion If $_g_ArrayDisplay_bUserFunc Then $hUser_Function = Default $bDebug = False EndIf If Not IsKeyword($hUser_Function) = $KEYWORD_DEFAULT Then $_g_ArrayDisplay_bUserFunc = True EndIf ; Default values If $sTitle = Default Then $sTitle = $sMsgBoxTitle If $sArrayRange = Default Then $sArrayRange = "" If $iFlags = Default Then $iFlags = $__g_ArrayDisplay_Share_iFlags If $iFlags = Default Then $iFlags = 0 If $vUser_Separator = Default Then $vUser_Separator = "" If $sHeader = Default Then $sHeader = "" Local $iMin_ColWidth = 55 Local $iMax_ColWidth = 350 ;~ If $iDesired_Colwidth = Default Then ; do not change predefined $iMin_ColWidth, $iMax_ColWidth If $iDesired_Colwidth > 0 Then $iMax_ColWidth = $iDesired_Colwidth If $iDesired_Colwidth < 0 Then $iMin_ColWidth = -$iDesired_Colwidth If $iMax_ColWidth = Default Then $iMax_ColWidth = 350 If $iMax_ColWidth > 4095 Then $iMax_ColWidth = 4095 ; needed as the structure inside the notify handler is declared as Static If $hUser_Function = Default Then $hUser_Function = 0 ; Check for transpose, column align, verbosity and "Row" column visibility $_g_ArrayDisplay_iTranspose = BitAND($iFlags, $ARRAYDISPLAY_TRANSPOSE) Local $iColAlign = BitAND($iFlags, 6) ; 0 = Left (default); 2 = Right; 4 = Center Local $iVerbose = Int(BitAND($iFlags, $ARRAYDISPLAY_VERBOSE)) $_g_ArrayDisplay_iDisplayRow = Int(BitAND($iFlags, $ARRAYDISPLAY_NOROW) = 0) Local $iRightClickClipPut = True If BitAND($iFlags, $ARRAYDISPLAY_NoRightClick) = $ARRAYDISPLAY_NoRightClick Then $iRightClickClipPut = False ; Set lower button border ;Local $iButtonBorder = (($bDebug) ? (40) : (20)) If IsDeclared("iButtonBorder") = $DECLARED_UNKNOWN Then Local $iButtonBorder $iButtonBorder = 40 If $bDebug Then Select Case Not BitAND($iFlags, $ARRAYDISPLAY_NODATALABELDISPLAY) And BitAND($iFlags, $ARRAYDISPLAY_NOBUTTONSDISPLAY) ;Allow border to show data label $iButtonBorder = 20 Case BitAND($iFlags, $ARRAYDISPLAY_NOBUTTONSDISPLAY) ;No border required for buttons or label (see above, NODATALABELDISPLAY = True) $iButtonBorder = 0 Case Not BitAND($iFlags, $ARRAYDISPLAY_ONLYCOPYBUTTONS) ;Allow border to show both copy & exit buttons (& data label if required) $iButtonBorder = 40 Case BitAND($iFlags, $ARRAYDISPLAY_ONLYCOPYBUTTONS) And Not BitAND($iFlags, $ARRAYDISPLAY_NODATALABELDISPLAY) ; Allow border to show copy buttons & data label (no exit button required) $iButtonBorder = 40 Case Not BitAND($iFlags, $ARRAYDISPLAY_NODATALABELDISPLAY) ;Allow border to show copy buttons, data label & exit button (NODATALABELDISPLAY = False) $iButtonBorder = 40 Case BitAND($iFlags, $ARRAYDISPLAY_ONLYCOPYBUTTONS) And BitAND($iFlags, $ARRAYDISPLAY_NODATALABELDISPLAY) ;Allow border to show copy buttons (no data label) $iButtonBorder = 20 Case Else $iButtonBorder = 40 EndSelect Else $iButtonBorder = 20 ;Allow border to show data label as there's no NODATALABELDISPLAY option for _ArrayDisplay() EndIf #Region Check valid array Local $sMsg = "", $iRet = 1 Local $fTimer = 0 If IsArray($aArray) Then $_g_ArrayDisplay_aArray = $aArray $_g_ArrayDisplay_iDims = UBound($_g_ArrayDisplay_aArray, $UBOUND_DIMENSIONS) If $_g_ArrayDisplay_iDims = 1 Then $_g_ArrayDisplay_iTranspose = 0 $_g_ArrayDisplay_nRows = UBound($_g_ArrayDisplay_aArray, $UBOUND_ROWS) $_g_ArrayDisplay_nCols = ($_g_ArrayDisplay_iDims = 2) ? UBound($_g_ArrayDisplay_aArray, $UBOUND_COLUMNS) : 1 ; Split custom header on separator Dim $_g_ArrayDisplay_aNumericSort[$_g_ArrayDisplay_nCols] ; Dimension checking If $_g_ArrayDisplay_iDims > 2 Then $sMsg = "Larger than 2D array passed to function" $iRet = 2 EndIf If $_iCallerError Then If $bDebug Then ; Call _DebugReport() if available If IsDeclared("__g_sReportCallBack_DebugReport_Debug") Then $sMsg = "@@ Debug( " & $_iScriptLineNumber & ") : @error = " & $_iCallerError & " in " & $sMsgBoxTitle & "( '" & $sTitle & "' )" Execute('$__g_sReportCallBack_DebugReport_Debug("' & $sMsg & '")') EndIf $iRet = 3 ElseIf BitAND($iFlags, $ARRAYDISPLAY_CHECKERROR) Then $sMsg = "@error = " & $_iCallerError & " when calling the function" If $_iScriptLineNumber > 0 Then $sMsg &= " at line " & $_iScriptLineNumber $iRet = 3 EndIf EndIf Else $sMsg = "No array variable passed to function" EndIf If $sMsg Then If $iVerbose And MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR + $MB_YESNO, _ $sMsgBoxTitle & "() Error: " & $sTitle, $sMsg & @CRLF & @CRLF & "Exit the script?") = $IDYES Then Exit Else Return SetError($iRet, 0, 0) EndIf EndIf #EndRegion Check valid array #Region Check array range ; Determine copy separator Local $iCW_ColWidth = Number($vUser_Separator) ; Get current separator character Local $sCurr_Separator = Opt("GUIDataSeparatorChar") ; Set default user separator if required If $vUser_Separator = "" Then $vUser_Separator = $sCurr_Separator ; Declare variables $_g_ArrayDisplay_iItem_Start = 0 $_g_ArrayDisplay_iItem_End = $_g_ArrayDisplay_nRows - 1 $_g_ArrayDisplay_iSubItem_Start = 0 $_g_ArrayDisplay_iSubItem_End = (($_g_ArrayDisplay_iDims = 2) ? ($_g_ArrayDisplay_nCols - 1) : (0)) Local $avRangeSplit ; Check for range settings If $sArrayRange Then ; Split into separate dimension sections Local $vTmp, $aArray_Range = StringRegExp($sArrayRange & "||", "(?U)(.*)\|", $STR_REGEXPARRAYGLOBALMATCH) ; Rows range If $aArray_Range[0] Then $avRangeSplit = StringSplit($aArray_Range[0], ":") If @error Then $_g_ArrayDisplay_iItem_End = Number($aArray_Range[0]) Else $_g_ArrayDisplay_iItem_Start = Number($avRangeSplit[1]) If $avRangeSplit[2] <> "" Then $_g_ArrayDisplay_iItem_End = Number($avRangeSplit[2]) EndIf EndIf EndIf ; Check row bounds If $_g_ArrayDisplay_iItem_Start < 0 Then $_g_ArrayDisplay_iItem_Start = 0 If $_g_ArrayDisplay_iItem_End >= $_g_ArrayDisplay_nRows Then $_g_ArrayDisplay_iItem_End = $_g_ArrayDisplay_nRows - 1 If ($_g_ArrayDisplay_iItem_Start > $_g_ArrayDisplay_iItem_End) And ($_g_ArrayDisplay_iItem_End > 0) Then $vTmp = $_g_ArrayDisplay_iItem_Start $_g_ArrayDisplay_iItem_Start = $_g_ArrayDisplay_iItem_End $_g_ArrayDisplay_iItem_End = $vTmp EndIf ; Columns range If $_g_ArrayDisplay_iDims = 2 And $aArray_Range[1] Then $avRangeSplit = StringSplit($aArray_Range[1], ":") If @error Then $_g_ArrayDisplay_iSubItem_End = Number($aArray_Range[1]) Else $_g_ArrayDisplay_iSubItem_Start = Number($avRangeSplit[1]) If $avRangeSplit[2] <> "" Then $_g_ArrayDisplay_iSubItem_End = Number($avRangeSplit[2]) EndIf EndIf ; Check column bounds If $_g_ArrayDisplay_iSubItem_Start > $_g_ArrayDisplay_iSubItem_End Then $vTmp = $_g_ArrayDisplay_iSubItem_Start $_g_ArrayDisplay_iSubItem_Start = $_g_ArrayDisplay_iSubItem_End $_g_ArrayDisplay_iSubItem_End = $vTmp EndIf If $_g_ArrayDisplay_iSubItem_Start < 0 Then $_g_ArrayDisplay_iSubItem_Start = 0 If $_g_ArrayDisplay_iSubItem_End >= $_g_ArrayDisplay_nCols Then $_g_ArrayDisplay_iSubItem_End = $_g_ArrayDisplay_nCols - 1 EndIf EndIf ; Create data display Local $sDisplayData = "[" & $_g_ArrayDisplay_nRows & "]" If $_g_ArrayDisplay_iDims = 2 Then $sDisplayData &= " [" & $_g_ArrayDisplay_nCols & "]" EndIf ; Create tooltip data Local $sTipData = "" If $sArrayRange Then If $sTipData Then $sTipData &= " - " $sTipData &= "Range set " & $sArrayRange EndIf If $_g_ArrayDisplay_iTranspose Then If $sTipData Then $sTipData &= " - " $sTipData &= "Transposed" EndIf If $sArrayRange Or $_g_ArrayDisplay_iTranspose Then $_g_ArrayDisplay_aArray = __ArrayDisplay_CreateSubArray() #EndRegion Check array range #Region Check custom header ; Split custom header on separator $_g_ArrayDisplay_asHeader = StringSplit($sHeader, $sCurr_Separator, $STR_NOCOUNT) ; No count element If UBound($_g_ArrayDisplay_asHeader) = 0 Then Dim $_g_ArrayDisplay_asHeader[1] = [""] $sHeader = "Row" Local $iIndex = $_g_ArrayDisplay_iSubItem_Start If $_g_ArrayDisplay_iTranspose Then ; All default headers $sHeader = "Row" For $j = 0 To $_g_ArrayDisplay_nCols - 1 $sHeader &= $sCurr_Separator & $ARRAYDISPLAY_ROWPREFIX & " " & $j + $_g_ArrayDisplay_iSubItem_Start Next Else ; Create custom header with available items If $_g_ArrayDisplay_asHeader[0] Then ; Set as many as available For $iIndex = $_g_ArrayDisplay_iSubItem_Start To $_g_ArrayDisplay_iSubItem_End ; Check custom header available If $iIndex >= UBound($_g_ArrayDisplay_asHeader) Then ExitLoop If StringRight($_g_ArrayDisplay_asHeader[$iIndex], 1) = $ARRAYDISPLAY_NUMERICSORT Then $_g_ArrayDisplay_asHeader[$iIndex] = StringTrimRight($_g_ArrayDisplay_asHeader[$iIndex], 1) ; remove "*" from right $_g_ArrayDisplay_aNumericSort[$iIndex - $_g_ArrayDisplay_iSubItem_Start] = 1 ; 1 (numeric sort) or empty (natural sort) EndIf $sHeader &= $sCurr_Separator & $_g_ArrayDisplay_asHeader[$iIndex] Next EndIf ; Add default headers to fill to end For $j = $iIndex To $_g_ArrayDisplay_iSubItem_End $sHeader &= $sCurr_Separator & "Col " & $j Next EndIf ; Remove "Row" header if not needed If Not $_g_ArrayDisplay_iDisplayRow Then $sHeader = StringTrimLeft($sHeader, 4) #EndRegion Check custom header #Region Generate Sort index for columns __ArrayDisplay_SortIndexes(0, -1) ; compute the time to generate one colum info to to the sorting Local $hTimer = TimerInit() __ArrayDisplay_SortIndexes(1, 1) $fTimer = TimerDiff($hTimer) If $fTimer * $_g_ArrayDisplay_nCols < 1000 Then ; __ArrayDisplay_SortIndexes(-1) __ArrayDisplay_SortIndexes(2, $_g_ArrayDisplay_nCols) ;~ If $bDebug Then ConsoleWrite("Sorting all indexes = " & TimerDiff($hTimer) & @CRLF & @CRLF) Else ;~ If $bDebug Then ConsoleWrite("Sorting one index = " & TimerDiff($hTimer) & @CRLF) EndIf #EndRegion Generate Sort index for columns #Region GUI and Listview generation ; Display splash dialog if required If $iVerbose And ($_g_ArrayDisplay_nRows * $_g_ArrayDisplay_nCols) > 1000 Then SplashTextOn($sMsgBoxTitle, "Preparing display" & @CRLF & @CRLF & "Please be patient", 300, 100) EndIf ; GUI Constants Local Const $_ARRAYCONSTANT_GUI_DOCKBOTTOM = 64 Local Const $_ARRAYCONSTANT_GUI_DOCKBORDERS = 102 Local Const $_ARRAYCONSTANT_GUI_DOCKHEIGHT = 512 Local Const $_ARRAYCONSTANT_GUI_DOCKLEFT = 2 Local Const $_ARRAYCONSTANT_GUI_DOCKRIGHT = 4 Local Const $_ARRAYCONSTANT_GUI_DOCKHCENTER = 8 Local Const $_ARRAYCONSTANT_GUI_EVENT_CLOSE = -3 Local Const $_ARRAYCONSTANT_GUI_EVENT_ARRAY = 1 Local Const $_ARRAYCONSTANT_GUI_FOCUS = 256 Local Const $_ARRAYCONSTANT_SS_CENTER = 0x1 Local Const $_ARRAYCONSTANT_SS_CENTERIMAGE = 0x0200 Local Const $_ARRAYCONSTANT_LVM_GETITEMRECT = (0x1000 + 14) Local Const $_ARRAYCONSTANT_LVM_GETITEMSTATE = (0x1000 + 44) Local Const $_ARRAYCONSTANT_LVM_GETSELECTEDCOUNT = (0x1000 + 50) Local Const $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE = (0x1000 + 54) Local Const $_ARRAYCONSTANT_LVS_EX_GRIDLINES = 0x1 Local Const $_ARRAYCONSTANT_LVIS_SELECTED = 0x0002 Local Const $_ARRAYCONSTANT_LVS_SHOWSELALWAYS = 0x8 Local Const $_ARRAYCONSTANT_LVS_OWNERDATA = 0x1000 Local Const $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT = 0x20 Local Const $_ARRAYCONSTANT_LVS_EX_DOUBLEBUFFER = 0x00010000 ; Paints via double-buffering, which reduces flicker Local Const $_ARRAYCONSTANT_WS_EX_CLIENTEDGE = 0x0200 Local Const $_ARRAYCONSTANT_WS_MAXIMIZEBOX = 0x00010000 Local Const $_ARRAYCONSTANT_WS_MINIMIZEBOX = 0x00020000 Local Const $_ARRAYCONSTANT_WS_SIZEBOX = 0x00040000 ; Set coord mode 1 Local $iCoordMode = Opt("GUICoordMode", 1) ; Create GUI Local $iOrgWidth = 210, $iHeight = 200, $iMinSize = 250 Local $hGUI = GUICreate($sTitle, $iOrgWidth, $iHeight, Default, Default, BitOR($_ARRAYCONSTANT_WS_SIZEBOX, $_ARRAYCONSTANT_WS_MINIMIZEBOX, $_ARRAYCONSTANT_WS_MAXIMIZEBOX)) Local $aiGUISize = WinGetClientSize($hGUI) ; Create ListView Local $idListView = GUICtrlCreateListView($sHeader, 0, 0, $aiGUISize[0], $aiGUISize[1] - $iButtonBorder, BitOR($_ARRAYCONSTANT_LVS_SHOWSELALWAYS, $_ARRAYCONSTANT_LVS_OWNERDATA)) $_g_ArrayDisplay_hListView = GUICtrlGetHandle($idListView) GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_GRIDLINES, $_ARRAYCONSTANT_LVS_EX_GRIDLINES) GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT, $_ARRAYCONSTANT_LVS_EX_FULLROWSELECT) GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_LVS_EX_DOUBLEBUFFER, $_ARRAYCONSTANT_LVS_EX_DOUBLEBUFFER) GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_SETEXTENDEDLISTVIEWSTYLE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE, $_ARRAYCONSTANT_WS_EX_CLIENTEDGE) Local $hHeader = HWnd(GUICtrlSendMsg($idListView, (0x1000 + 31), 0, 0)) ; $LVM_GETHEADER _GUICtrlListView_GetHeader($idListView) ; Set resizing GUICtrlSetResizing($idListView, $_ARRAYCONSTANT_GUI_DOCKBORDERS) ; Fill listview Local $iColFill = $_g_ArrayDisplay_nCols + $_g_ArrayDisplay_iDisplayRow ; Align columns if required - $iColAlign = 2 for Right and 4 for Center If $iColAlign Then ; Loop through columns For $i = 0 To $iColFill - 1 __ArrayDisplay_JustifyColumn($idListView, $i, $iColAlign / 2) Next EndIf GUICtrlSendMsg($idListView, (0x1000 + 47), $_g_ArrayDisplay_nRows, 0) ; $LVM_SETITEMCOUNT ; Get row height Local $tRECT = DllStructCreate("struct; long Left;long Top;long Right;long Bottom; endstruct") ; $tagRECT DllCall("user32.dll", "struct*", "SendMessageW", "hwnd", $_g_ArrayDisplay_hListView, "uint", $_ARRAYCONSTANT_LVM_GETITEMRECT, "wparam", 0, "struct*", $tRECT) ; Set required GUI height Local $aiWin_Pos = WinGetPos($hGUI) Local $aiLV_Pos = ControlGetPos($hGUI, "", $idListView) $iHeight = (($_g_ArrayDisplay_nRows + 3) * (DllStructGetData($tRECT, "Bottom") - DllStructGetData($tRECT, "Top"))) + $aiWin_Pos[3] - $aiLV_Pos[3] ; Check min/max height If $iHeight > @DesktopHeight - 100 Then $iHeight = @DesktopHeight - 100 ElseIf $iHeight < $iMinSize Then $iHeight = $iMinSize EndIf If $iVerbose Then SplashOff() ; Sorting information $_g_ArrayDisplay_iSortDir = 0x00000400 ; $HDF_SORTUP Local $iColumn = 0, $iColumnPrev = -1 If $_g_ArrayDisplay_iDisplayRow Then $iColumnPrev = $iColumn __ArrayDisplay_HeaderSetItemFormat($hHeader, $iColumn, 0x00004000 + $_g_ArrayDisplay_iSortDir + $iColAlign / 2) ; $HDF_STRING EndIf $_g_ArrayDisplay_aIndex = $_g_ArrayDisplay_aIndexes[0] #EndRegion GUI and Listview generation ; Register WM_NOTIFY message handler through subclassing Local $p__ArrayDisplay_NotifyHandler = DllCallbackGetPtr(DllCallbackRegister("__ArrayDisplay_NotifyHandler", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr")) DllCall("comctl32.dll", "bool", "SetWindowSubclass", "hwnd", $hGUI, "ptr", $p__ArrayDisplay_NotifyHandler, "uint_ptr", 0, "dword_ptr", 0) ; $iSubclassId = 0, $pData = 0 #Region Adjust dialog width Local $iWidth = 40, $iColWidth = 0, $aiColWidth[$iColFill] ; Get required column widths to fit items Local $iColWidthHeader, $iMin_ColW = 55 For $i = 0 To $iColFill - 1 If $i > 0 Then $iMin_ColW = $iMin_ColWidth ; to be use only for #col > 0 GUICtrlSendMsg($idListView, (0x1000 + 30), $i, -1) ; $LVM_SETCOLUMNWIDTH $LVSCW_AUTOSIZE $iColWidth = GUICtrlSendMsg($idListView, (0x1000 + 29), $i, 0) ; $LVM_GETCOLUMNWIDTH ; Check width of header if set If $sHeader <> "" Then If $iColWidth = 0 Then ExitLoop GUICtrlSendMsg($idListView, (0x1000 + 30), $i, -2) ; $LVM_SETCOLUMNWIDTH $LVSCW_AUTOSIZE_USEHEADER $iColWidthHeader = GUICtrlSendMsg($idListView, (0x1000 + 29), $i, 0) ; $GETCOLUMNWIDTH ; Set minimum if required If $iColWidth < $iMin_ColW And $iColWidthHeader < $iMin_ColW Then GUICtrlSendMsg($idListView, (0x1000 + 30), $i, $iMin_ColW) ; $LVM_SETCOLUMNWIDTH $iColWidth = $iMin_ColW ElseIf $iColWidthHeader < $iColWidth Then GUICtrlSendMsg($idListView, (0x1000 + 30), $i, $iColWidth) ; $LVM_SETCOLUMNWIDTH Else $iColWidth = $iColWidthHeader EndIf Else ; Set minimum if required If $iColWidth < $iMin_ColW Then GUICtrlSendMsg($idListView, (0x1000 + 30), $i, $iMin_ColW) ; $LVM_SETCOLUMNWIDTH $iColWidth = $iMin_ColW EndIf EndIf ; Add to total width $iWidth += $iColWidth ; Store value $aiColWidth[$i] = $iColWidth Next ; Now check max size If $iWidth > @DesktopWidth - 100 Then ; Apply max col width limit to reduce width $iWidth = 40 For $i = 0 To $iColFill - 1 If $aiColWidth[$i] > $iMax_ColWidth Then ; Reset width GUICtrlSendMsg($idListView, (0x1000 + 30), $i, $iMax_ColWidth) ; $LVM_SETCOLUMNWIDTH $iWidth += $iMax_ColWidth Else ; Retain width $iWidth += $aiColWidth[$i] EndIf If $i < 20 And $bDebug Then ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iWidth = ' & $iWidth & " $i = " & $i & @CRLF) ;### Debug Console Next EndIf ; Check max/min width If $iWidth > @DesktopWidth - 100 Then $iWidth = @DesktopWidth - 100 ElseIf $iWidth < $iMinSize Then $iWidth = $iMinSize EndIf #EndRegion Adjust dialog width ; Allow for borders with vertical scrollbar Local $iScrollBarSize = 0 If $iHeight = (@DesktopHeight - 100) Then $iScrollBarSize = 15 ; Resize dialog WinMove($hGUI, "", (@DesktopWidth - $iWidth + $iScrollBarSize) / 2, (@DesktopHeight - $iHeight) / 2, $iWidth + $iScrollBarSize, $iHeight) ; Resize ListView $aiGUISize = WinGetClientSize($hGUI) GUICtrlSetPos($idListView, 0, 0, $iWidth, $aiGUISize[1] - $iButtonBorder) #Region Create bottom infos Local $iButtonWidth_1 = $aiGUISize[0] / 2 Local $iButtonWidth_2 = $aiGUISize[0] / 3 Local $idCopy_ID = 9999, $idCopy_Data = 99999, $idData_Label = 99999, $idUser_Func = 99999, $idExit_Script = 99999 If $bDebug Then ; Create buttons $idCopy_ID = GUICtrlCreateButton("Copy Data && Hdr/Row", 0, $aiGUISize[1] - $iButtonBorder, $iButtonWidth_1, 20) $idCopy_Data = GUICtrlCreateButton("Copy Data Only", $iButtonWidth_1, $aiGUISize[1] - $iButtonBorder, $iButtonWidth_1, 20) ; Check if other buttons are required If Not BitAND($iFlags, $ARRAYDISPLAY_ONLYCOPYBUTTONS) And Not BitAND($iFlags, $ARRAYDISPLAY_NOBUTTONSDISPLAY) Then Local $iButtonWidth_Var = $iButtonWidth_1 Local $iOffset = $iButtonWidth_1 If IsFunc($hUser_Function) Then ; Create UserFunc button if function passed $idUser_Func = GUICtrlCreateButton("Run User Func", $iButtonWidth_2, $aiGUISize[1] - 20, $iButtonWidth_2, 20) $iButtonWidth_Var = $iButtonWidth_2 $iOffset = $iButtonWidth_2 * 2 EndIf ; Create Exit button and data label $idExit_Script = GUICtrlCreateButton("Exit", $iOffset, $aiGUISize[1] - 20, $iButtonWidth_Var, 20) ;$idData_Label = GUICtrlCreateLabel($sDisplayData, 0, $aiGUISize[1] - 20, $iButtonWidth_Var, 18, BitOR($_ARRAYCONSTANT_SS_CENTER, $_ARRAYCONSTANT_SS_CENTERIMAGE)) If Not BitAND($iFlags, $ARRAYDISPLAY_NODATALABELDISPLAY) Then $idData_Label = GUICtrlCreateLabel($sDisplayData, 0, $aiGUISize[1] - 20, $iButtonWidth_Var, 18, BitOR($_ARRAYCONSTANT_SS_CENTER, $_ARRAYCONSTANT_SS_CENTERIMAGE)) Else If Not BitAND($iFlags, $ARRAYDISPLAY_NODATALABELDISPLAY) Then $idData_Label = GUICtrlCreateLabel($sDisplayData, 0, $aiGUISize[1] - 20, $aiGUISize[0], 18, BitOR($_ARRAYCONSTANT_SS_CENTER, $_ARRAYCONSTANT_SS_CENTERIMAGE)) EndIf Else $idData_Label = GUICtrlCreateLabel($sDisplayData, 0, $aiGUISize[1] - 20, $aiGUISize[0], 18, BitOR($_ARRAYCONSTANT_SS_CENTER, $_ARRAYCONSTANT_SS_CENTERIMAGE)) EndIf ; Change label colour and create tooltip if required If $_g_ArrayDisplay_iTranspose Or $sArrayRange Then GUICtrlSetColor($idData_Label, 0xFF0000) GUICtrlSetTip($idData_Label, $sTipData) EndIf GUICtrlSetResizing($idCopy_ID, $_ARRAYCONSTANT_GUI_DOCKLEFT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT) GUICtrlSetResizing($idCopy_Data, $_ARRAYCONSTANT_GUI_DOCKRIGHT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT) GUICtrlSetResizing($idData_Label, $_ARRAYCONSTANT_GUI_DOCKLEFT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT) GUICtrlSetResizing($idUser_Func, $_ARRAYCONSTANT_GUI_DOCKHCENTER + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT) GUICtrlSetResizing($idExit_Script, $_ARRAYCONSTANT_GUI_DOCKRIGHT + $_ARRAYCONSTANT_GUI_DOCKBOTTOM + $_ARRAYCONSTANT_GUI_DOCKHEIGHT) #EndRegion Create bottom infos ; Display dialog GUISetState(@SW_SHOW, $hGUI) ; Check if sort clicking can take a while If $fTimer > 1000 And Not $sArrayRange Then Beep(750, 250) ToolTip("Sorting Action can take as long as " & Ceiling($fTimer / 1000) & " sec" & @CRLF & @CRLF & "Please be patient when you click to sort a column", 50, 50, $sMsgBoxTitle, $TIP_WARNINGICON, $TIP_BALLOON) Sleep(3000) ToolTip("") EndIf #Region GUI Handling events ; Switch to GetMessage mode Local $iOnEventMode = Opt("GUIOnEventMode", 0), $aMsg ConsoleWrite("__ArrayDisplay_Share() loadded in: " & TimerDiff($hRetTimer) & @CRLF) While 1 $aMsg = GUIGetMsg($_ARRAYCONSTANT_GUI_EVENT_ARRAY) ; Variable needed to check which "Copy" button was pressed If $__g_ArrayDisplay_Timeout_msReturn Then If TimerDiff($hRetTimer) > $__g_ArrayDisplay_Timeout_msReturn Then ExitLoop EndIf If $__g_ArrayDisplay_Timeout_msExit Then If TimerDiff($hRetTimer) > $__g_ArrayDisplay_Timeout_msExit Then GUIDelete($hGUI) Exit $__g_ArrayDisplay_Timeout_ecExit EndIf EndIf If $aMsg[1] = $hGUI Then Switch $aMsg[0] Case $GUI_EVENT_MINIMIZE If $__g_ArrayDisplay_Timeout_msReturn Or $__g_ArrayDisplay_Timeout_msExit Then $__g_ArrayDisplay_Timeout_msReturn = 0 $__g_ArrayDisplay_Timeout_msExit = 0 WinSetTitle($hGUI, "", '(#) ' & $sTitle) EndIf Case $_ARRAYCONSTANT_GUI_EVENT_CLOSE ExitLoop Case $GUI_EVENT_SECONDARYUP If $iRightClickClipPut Then __ArrayDisplay_SubItemHitTest_ClipPut($idListView) Case $idCopy_ID, $idCopy_Data ; Count selected rows Local $iSel_Count = GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_GETSELECTEDCOUNT, 0, 0) ; Display splash dialog if required If $iVerbose And (Not $iSel_Count) And ($_g_ArrayDisplay_iItem_End - $_g_ArrayDisplay_iItem_Start) * ($_g_ArrayDisplay_iSubItem_End - $_g_ArrayDisplay_iSubItem_Start) > 10000 Then SplashTextOn($sMsgBoxTitle, "Copying data" & @CRLF & @CRLF & "Please be patient", 300, 100) EndIf ; Generate clipboard text Local $sClip = "", $sItem, $aSplit, $iFirstCol = 0 If $aMsg[0] = $idCopy_Data And $_g_ArrayDisplay_iDisplayRow Then $iFirstCol = 1 ; Add items For $i = 0 To GUICtrlSendMsg($idListView, 0X1004, 0, 0) - 1 ; $LVM_GETITEMCOUNT ; Skip if copying selected rows and item not selected If $iSel_Count And Not (GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_GETITEMSTATE, $i, $_ARRAYCONSTANT_LVIS_SELECTED) <> 0) Then ContinueLoop EndIf $sItem = __ArrayDisplay_GetItemTextStringSelected($idListView, $i, $iFirstCol) If $aMsg[0] = $idCopy_ID And Not $_g_ArrayDisplay_iDisplayRow Then ; Add row data $sItem = $ARRAYDISPLAY_ROWPREFIX & " " & ($i + $_g_ArrayDisplay_iItem_Start) & $sCurr_Separator & $sItem EndIf If $iCW_ColWidth Then ; Expand columns $aSplit = StringSplit($sItem, $sCurr_Separator) $sItem = "" For $j = 1 To $aSplit[0] $sItem &= StringFormat("%-" & $iCW_ColWidth + 1 & "s", StringLeft($aSplit[$j], $iCW_ColWidth)) Next Else ; Use defined separator $sItem = StringReplace($sItem, $sCurr_Separator, $vUser_Separator) EndIf $sClip &= $sItem & @CRLF Next $sItem = $sHeader ; Add header line if required If $aMsg[0] = $idCopy_ID Then $sItem = $sHeader If Not $_g_ArrayDisplay_iDisplayRow Then ; Add "Row" to header $sItem = "Row" & $sCurr_Separator & $sItem EndIf If $iCW_ColWidth Then $aSplit = StringSplit($sItem, $sCurr_Separator) $sItem = "" For $j = 1 To $aSplit[0] $sItem &= StringFormat("%-" & $iCW_ColWidth + 1 & "s", StringLeft($aSplit[$j], $iCW_ColWidth)) Next Else $sItem = StringReplace($sItem, $sCurr_Separator, $vUser_Separator) EndIf $sClip = $sItem & @CRLF & $sClip EndIf ;Send to clipboard ClipPut($sClip) ; Remove splash if used SplashOff() ; Refocus ListView GUICtrlSetState($idListView, $_ARRAYCONSTANT_GUI_FOCUS) Case $idListView $iColumn = GUICtrlGetState($idListView) If Not IsArray($_g_ArrayDisplay_aIndexes[$iColumn + Not $_g_ArrayDisplay_iDisplayRow]) Then ; in case all indexes have not been set during start creation __ArrayDisplay_SortIndexes($iColumn + Not $_g_ArrayDisplay_iDisplayRow) EndIf If $iColumn <> $iColumnPrev Then __ArrayDisplay_HeaderSetItemFormat($hHeader, $iColumnPrev, 0x00004000 + $iColAlign / 2) ; $HDF_STRING If $_g_ArrayDisplay_iDisplayRow And $iColumn = 0 Then $_g_ArrayDisplay_aIndex = $_g_ArrayDisplay_aIndexes[0] Else $_g_ArrayDisplay_aIndex = $_g_ArrayDisplay_aIndexes[$iColumn + Not $_g_ArrayDisplay_iDisplayRow] EndIf EndIf ; $_g_ArrayDisplay_iSortDir = ($iColumn = $iColumnPrev) ? $_g_ArrayDisplay_iSortDir = $HDF_SORTUP ? $HDF_SORTDOWN : $HDF_SORTUP : $HDF_SORTUP $_g_ArrayDisplay_iSortDir = ($iColumn = $iColumnPrev) ? $_g_ArrayDisplay_iSortDir = 0x00000400 ? 0x00000200 : 0x00000400 : 0x00000400 ; $HDF_SORTUP __ArrayDisplay_HeaderSetItemFormat($hHeader, $iColumn, 0x00004000 + $_g_ArrayDisplay_iSortDir + $iColAlign / 2) ; $HDF_STRING GUICtrlSendMsg($idListView, (0x1000 + 140), $iColumn, 0) ; $LVM_SETSELECTEDCOLUMN GUICtrlSendMsg($idListView, (0x1000 + 47), $_g_ArrayDisplay_nRows, 0) ; $LVM_SETITEMCOUNT $iColumnPrev = $iColumn Case $idUser_Func ; Get selected indices Local $aiSelItems[1] = [0] For $i = 0 To GUICtrlSendMsg($idListView, 0x1004, 0, 0) - 1 ; $LVM_GETITEMCOUNT If (GUICtrlSendMsg($idListView, $_ARRAYCONSTANT_LVM_GETITEMSTATE, $i, $_ARRAYCONSTANT_LVIS_SELECTED) <> 0) Then $aiSelItems[0] += 1 ReDim $aiSelItems[$aiSelItems[0] + 1] $aiSelItems[$aiSelItems[0]] = $i + $_g_ArrayDisplay_iItem_Start EndIf Next ; Pass array and selection to user function $hUser_Function($_g_ArrayDisplay_aArray, $aiSelItems) $_g_ArrayDisplay_bUserFunc = False __ArrayDisplay_CleanUp($hGUI, $iCoordMode, $iOnEventMode, $_iCallerError, $_iCallerExtended, $p__ArrayDisplay_NotifyHandler) ;;__ArrayDisplay_Share($aArray, $sTitle, $sArrayRange, $iFlags, $vUser_Separator, $sHeader, $iMax_ColWidth, $hUser_Function, $bDebug, $_iScriptLineNumber, $_iCallerError, $_iCallerExtended) Return SetError($_iCallerError, $_iCallerExtended, -1) Case $idExit_Script ; Clear up GUIDelete($hGUI) Exit EndSwitch EndIf WEnd #EndRegion GUI Handling events __ArrayDisplay_CleanUp($hGUI, $iCoordMode, $iOnEventMode, $_iCallerError, $_iCallerExtended, $p__ArrayDisplay_NotifyHandler) Return SetError($_iCallerError, $_iCallerExtended, 1) EndFunc ;==>__ArrayDisplay_Share Func __ArrayDisplay_CleanUp($hGUI, $iCoordMode, $iOnEventMode, $_iCallerError, $_iCallerExtended, $p__ArrayDisplay_NotifyHandler) ; Cleanup DllCall("comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $hGUI, "ptr", $p__ArrayDisplay_NotifyHandler, "uint_ptr", 0) ; $iSubclassId = 0 ; Release resources in case of big array used $_g_ArrayDisplay_aIndex = 0 Dim $_g_ArrayDisplay_aIndexes[1] GUIDelete($hGUI) Opt("GUICoordMode", $iCoordMode) ; Reset original Coord mode Opt("GUIOnEventMode", $iOnEventMode) ; Reset original GUI mode Return SetError($_iCallerError, $_iCallerExtended, 1) EndFunc ;==>__ArrayDisplay_CleanUp ; #ADDITIONAL Functions to speed up _ArrayDisplay() or _DebugArrayDisplay()# ==================================================== ; Thanks Larsj Func __ArrayDisplay_NotifyHandler($hWnd, $iMsg, $wParam, $lParam, $iSubclassId, $pData) If $iMsg <> 0x004E Then Return DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)[0] ; 0x004E = $WM_NOTIFY Local Static $tagNMHDR = "struct;hwnd hWndFrom;uint_ptr IDFrom;INT Code;endstruct" Local Static $tagNMLVDISPINFO = $tagNMHDR & ";" & $_ARRAYCONSTANT_tagLVITEM Local $tNMLVDISPINFO = DllStructCreate($tagNMLVDISPINFO, $lParam) Switch HWnd(DllStructGetData($tNMLVDISPINFO, "hWndFrom")) Case $_g_ArrayDisplay_hListView Switch DllStructGetData($tNMLVDISPINFO, "Code") Case -177 ; $LVN_GETDISPINFOW Local Static $tText = DllStructCreate("wchar[4096]"), $pText = DllStructGetPtr($tText) Local $iItem = DllStructGetData($tNMLVDISPINFO, "Item") Local $iRow = ($_g_ArrayDisplay_iSortDir = 0x00000400) ? $_g_ArrayDisplay_aIndex[$iItem] : $_g_ArrayDisplay_aIndex[$_g_ArrayDisplay_nRows - 1 - $iItem] Local $iCol = DllStructGetData($tNMLVDISPINFO, "SubItem") ;~ ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $iRow = ' & $iRow & ' $iCol= ' & $iCol & ' $iItem = ' & $iItem & @CRLF) ;### Debug Console Local $sTemp If $_g_ArrayDisplay_iDisplayRow = 0 Then $sTemp = __ArrayDisplay_GetData($iRow, $iCol) DllStructSetData($tText, 1, $sTemp) DllStructSetData($tNMLVDISPINFO, "Text", $pText) Else If $iCol = 0 Then If $_g_ArrayDisplay_iTranspose Then Local $sCaptionCplt = "" If $iRow + $_g_ArrayDisplay_iItem_Start < UBound($_g_ArrayDisplay_asHeader) _ And StringStripWS($_g_ArrayDisplay_asHeader[$iRow + $_g_ArrayDisplay_iItem_Start], 1 + 2) <> "" Then $sCaptionCplt = " (" & StringStripWS($_g_ArrayDisplay_asHeader[$iRow + $_g_ArrayDisplay_iItem_Start], 1 + 2) If StringRight($sCaptionCplt, 1) = $ARRAYDISPLAY_NUMERICSORT Then $sCaptionCplt = StringTrimRight($sCaptionCplt, 1) $sCaptionCplt &= ")" EndIf DllStructSetData($tText, 1, "Col " & ($iRow + $_g_ArrayDisplay_iItem_Start) & $sCaptionCplt) Else DllStructSetData($tText, 1, $ARRAYDISPLAY_ROWPREFIX & " " & $iRow + $_g_ArrayDisplay_iItem_Start) EndIf DllStructSetData($tNMLVDISPINFO, "Text", $pText) Else $sTemp = __ArrayDisplay_GetData($iRow, $iCol - 1) DllStructSetData($tText, 1, $sTemp) DllStructSetData($tNMLVDISPINFO, "Text", $pText) EndIf EndIf Return EndSwitch EndSwitch Return DllCall("comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam)[0] #forceref $iSubclassId, $pData EndFunc ;==>__ArrayDisplay_NotifyHandler Func __ArrayDisplay_GetData($iRow, $iCol) Local $sTemp If $_g_ArrayDisplay_iDims = 2 Then $sTemp = $_g_ArrayDisplay_aArray[$iRow][$iCol] Else $sTemp = $_g_ArrayDisplay_aArray[$iRow] EndIf Switch VarGetType($sTemp) Case "Array" Local $sSubscript = "" For $i = 1 To UBound($sTemp, 0) $sSubscript = "[" & UBound($sTemp, $i) & "]" Next $sTemp = "{Array" & $sSubscript & "}" Case "Map" $sTemp = "{Map[" & UBound($sTemp) & "]}" Case "Object" $sTemp = "{Object}" EndSwitch If StringLen($sTemp) > 4095 Then $sTemp = StringLeft($sTemp, 4095) Return $sTemp EndFunc ;==>__ArrayDisplay_GetData Func __ArrayDisplay_SortIndexes($iColStart, $iColEnd = $iColStart) Dim $_g_ArrayDisplay_aIndex[$_g_ArrayDisplay_nRows] ;~ Local $hTimer If $iColEnd = -1 Then ; column (0) already sorted Dim $_g_ArrayDisplay_aIndexes[$_g_ArrayDisplay_nCols + $_g_ArrayDisplay_iDisplayRow + 1] ;~ $hTimer = TimerInit() For $i = 0 To $_g_ArrayDisplay_nRows - 1 $_g_ArrayDisplay_aIndex[$i] = $i Next $_g_ArrayDisplay_aIndexes[0] = $_g_ArrayDisplay_aIndex ;~ ConsoleWrite("Sorting array col#0 = " & TimerDiff($hTimer) & @CRLF) EndIf If $iColStart = -1 Then ; to index all columns $iColStart = 1 $iColEnd = $_g_ArrayDisplay_nCols EndIf If $iColStart Then ; Index aArray columns Local $tIndex For $i = $iColStart To $iColEnd ;~ $hTimer = TimerInit() $tIndex = __ArrayDisplay_GetSortColStruct($_g_ArrayDisplay_aArray, $i - 1) For $j = 0 To $_g_ArrayDisplay_nRows - 1 $_g_ArrayDisplay_aIndex[$j] = DllStructGetData($tIndex, 1, $j + 1) Next $_g_ArrayDisplay_aIndexes[$i] = $_g_ArrayDisplay_aIndex ;~ If $i < 20 Then ConsoleWrite("Sorting array col#" & $i & " = " & TimerDiff($hTimer) & @CRLF) Next EndIf EndFunc ;==>__ArrayDisplay_SortIndexes ; #INTERNAL_USE_ONLY# =========================================================================================================== ; Name...........: __ArrayDisplay_GetSortColStruct ; Description ...: Index based sorting of a 2D array by one or more columns ; Syntax.........: __ArrayDisplay_GetSortColStruct( $aArray, $iCol ) ; Parameters ....: $aArray The 2D array to be sorted by index ; $iCol Index column used in sorting ; Return values .: the sorting index as a DllStruct of integers ; Author ........: Larj : FAS_Sort2DArrayAu3() ; Modified.......: jpm : extension to 1D Array ; Remarks .......: ; =============================================================================================================================== Func __ArrayDisplay_GetSortColStruct(Const ByRef $aArray, $iCol) If UBound($aArray, $UBOUND_DIMENSIONS) < 1 Or UBound($aArray, $UBOUND_DIMENSIONS) > 2 Then ;~ ConsoleWrite("$aArray is not a 1D or 2D array variable" & @CRLF) Return SetError(6, 0, 0) EndIf Return __ArrayDisplay_SortArrayStruct($aArray, $iCol) EndFunc ;==>__ArrayDisplay_GetSortColStruct Func __ArrayDisplay_SortArrayStruct(Const ByRef $aArray, $iCol) Local $iDims = UBound($aArray, $UBOUND_DIMENSIONS) Local $tIndex = DllStructCreate("uint[" & $_g_ArrayDisplay_nRows & "]") Local $pIndex = DllStructGetPtr($tIndex) Static $hDll = DllOpen("kernel32.dll") Static $hDllComp = DllOpen("shlwapi.dll") Local $lo, $hi, $mi, $r, $nVal1, $nVal2 ; Sorting by one column For $i = 1 To $_g_ArrayDisplay_nRows - 1 $lo = 0 $hi = $i - 1 Do $mi = Int(($lo + $hi) / 2) If Not $_g_ArrayDisplay_iTranspose And $_g_ArrayDisplay_aNumericSort[$iCol] Then ; Numeric sort If $iDims = 1 Then $nVal1 = Number($aArray[$i]) $nVal2 = Number($aArray[DllStructGetData($tIndex, 1, $mi + 1)]) Else $nVal1 = Number($aArray[$i][$iCol]) $nVal2 = Number($aArray[DllStructGetData($tIndex, 1, $mi + 1)][$iCol]) EndIf $r = $nVal1 < $nVal2 ? -1 : $nVal1 > $nVal2 ? 1 : 0 Else ; Natural sort If $iDims = 1 Then $r = DllCall($hDllComp, 'int', 'StrCmpLogicalW', 'wstr', String($aArray[$i]), 'wstr', String($aArray[DllStructGetData($tIndex, 1, $mi + 1)]))[0] Else $r = DllCall($hDllComp, 'int', 'StrCmpLogicalW', 'wstr', String($aArray[$i][$iCol]), 'wstr', String($aArray[DllStructGetData($tIndex, 1, $mi + 1)][$iCol]))[0] EndIf EndIf Switch $r Case -1 $hi = $mi - 1 Case 1 $lo = $mi + 1 Case 0 ExitLoop EndSwitch Until $lo > $hi DllCall($hDll, "none", "RtlMoveMemory", "struct*", $pIndex + ($mi + 1) * 4, "struct*", $pIndex + $mi * 4, "ulong_ptr", ($i - $mi) * 4) DllStructSetData($tIndex, 1, $i, $mi + 1 + ($lo = $mi + 1)) Next Return $tIndex EndFunc ;==>__ArrayDisplay_SortArrayStruct Func __ArrayDisplay_CreateSubArray() ; the returned subarray is transposed Local $nRows = $_g_ArrayDisplay_iItem_End - $_g_ArrayDisplay_iItem_Start + 1 Local $nCols = $_g_ArrayDisplay_iSubItem_End - $_g_ArrayDisplay_iSubItem_Start + 1 Local $iRow = -1, $iCol, $iTemp, $aTemp If $_g_ArrayDisplay_iTranspose Then Dim $aTemp[$nCols][$nRows] For $i = $_g_ArrayDisplay_iItem_Start To $_g_ArrayDisplay_iItem_End $iRow += 1 $iCol = -1 For $j = $_g_ArrayDisplay_iSubItem_Start To $_g_ArrayDisplay_iSubItem_End $iCol += 1 $aTemp[$iCol][$iRow] = $_g_ArrayDisplay_aArray[$i][$j] Next Next $iTemp = $_g_ArrayDisplay_iItem_Start $_g_ArrayDisplay_iItem_Start = $_g_ArrayDisplay_iSubItem_Start $_g_ArrayDisplay_iSubItem_Start = $iTemp $iTemp = $_g_ArrayDisplay_iItem_End $_g_ArrayDisplay_iItem_End = $_g_ArrayDisplay_iSubItem_End $_g_ArrayDisplay_iSubItem_End = $iTemp $_g_ArrayDisplay_nRows = $nCols $_g_ArrayDisplay_nCols = $nRows Else If $_g_ArrayDisplay_iDims = 1 Then Dim $aTemp[$nRows] For $i = $_g_ArrayDisplay_iItem_Start To $_g_ArrayDisplay_iItem_End $iRow += 1 $aTemp[$iRow] = $_g_ArrayDisplay_aArray[$i] Next Else Dim $aTemp[$nRows][$nCols] For $i = $_g_ArrayDisplay_iItem_Start To $_g_ArrayDisplay_iItem_End $iRow += 1 $iCol = -1 For $j = $_g_ArrayDisplay_iSubItem_Start To $_g_ArrayDisplay_iSubItem_End $iCol += 1 $aTemp[$iRow][$iCol] = $_g_ArrayDisplay_aArray[$i][$j] Next Next $_g_ArrayDisplay_nCols = $nCols EndIf $_g_ArrayDisplay_nRows = $nRows EndIf ;~ _DebugArrayDisplay($aTemp, "Subarray") Return $aTemp EndFunc ;==>__ArrayDisplay_CreateSubArray ; #DUPLICATED Functions to avoid big #include "GuiHeader.au3"# ================================================================== ; Functions have been simplified (unicode inprocess) according to __ArrayDisplay_Share() needs Func __ArrayDisplay_HeaderSetItemFormat($hWnd, $iIndex, $iFormat) Local Static $tHDItem = DllStructCreate("uint Mask;int XY;ptr Text;handle hBMP;int TextMax;int Fmt;lparam Param;int Image;int Order;uint Type;ptr pFilter;uint State") ; $tagHDITEM DllStructSetData($tHDItem, "Mask", 0x00000004) ; $HDI_FORMAT DllStructSetData($tHDItem, "Fmt", $iFormat) Local $aResult = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hWnd, "uint", 0x120C, "wparam", $iIndex, "struct*", $tHDItem) ; $HDM_SETITEMW Return $aResult[0] <> 0 EndFunc ;==>__ArrayDisplay_HeaderSetItemFormat ; #DUPLICATED Functions to avoid big #include "GuiListView.au3"# ================================================================ ; Functions have been simplified (unicode inprocess) according to __ArrayDisplay_Share() needs Func __ArrayDisplay_GetItemText($idListView, $iIndex, $iSubItem = 0) Local $tBuffer = DllStructCreate("wchar Text[4096]") Local $pBuffer = DllStructGetPtr($tBuffer) Local $tItem = DllStructCreate($_ARRAYCONSTANT_tagLVITEM) DllStructSetData($tItem, "SubItem", $iSubItem) DllStructSetData($tItem, "TextMax", 4096) DllStructSetData($tItem, "Text", $pBuffer) ;Global Const $LVM_GETITEMTEXTW = (0x1000 + 115) ; 0X1073 If IsHWnd($idListView) Then DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $idListView, "uint", 0x1073, "wparam", $iIndex, "struct*", $tItem) Else Local $pItem = DllStructGetPtr($tItem) GUICtrlSendMsg($idListView, 0x1073, $iIndex, $pItem) EndIf Return DllStructGetData($tBuffer, "Text") EndFunc ;==>__ArrayDisplay_GetItemText Func __ArrayDisplay_GetItemTextStringSelected($idListView, $iItem, $iFirstCol) Local $sRow = "", $sSeparatorChar = Opt('GUIDataSeparatorChar') Local $iSelected = $iItem ; get row ; GetColumnCount Local $hHeader = HWnd(GUICtrlSendMsg($idListView, 0x101F, 0, 0)) ; $LVM_GETHEADER Local $nCol = DllCall("user32.dll", "lresult", "SendMessageW", "hwnd", $hHeader, "uint", 0x1200, "wparam", 0, "lparam", 0)[0] ; $HDM_GETITEMCOUNT For $x = $iFirstCol To $nCol - 1 $sRow &= __ArrayDisplay_GetItemText($idListView, $iSelected, $x) & $sSeparatorChar Next Return StringTrimRight($sRow, 1) EndFunc ;==>__ArrayDisplay_GetItemTextStringSelected Func __ArrayDisplay_JustifyColumn($idListView, $iIndex, $iAlign = -1) ;Local $aAlign[3] = [$LVCFMT_LEFT, $LVCFMT_RIGHT, $LVCFMT_CENTER] Local $tColumn = DllStructCreate("uint Mask;int Fmt;int CX;ptr Text;int TextMax;int SubItem;int Image;int Order;int cxMin;int cxDefault;int cxIdeal") ; $tagLVCOLUMN If $iAlign < 0 Or $iAlign > 2 Then $iAlign = 0 DllStructSetData($tColumn, "Mask", 0x01) ; $LVCF_FMT DllStructSetData($tColumn, "Fmt", $iAlign) Local $pColumn = DllStructGetPtr($tColumn) Local $iRet = GUICtrlSendMsg($idListView, 0x1060, $iIndex, $pColumn) ; $_ARRAYCONSTANT_LVM_SETCOLUMNW Return $iRet <> 0 EndFunc ;==>__ArrayDisplay_JustifyColumn because it'll be easier to see the easily patchable code (TM) techniques in action. Eventually you'll write cool stuff and I'd like to see that code ( for copy'n'paste ) and here is an example for the use of these helper functions: #include <Array.au3> _DebugArrayDisplay_TimeoutReturn(5000) ; timeout in 5 sec Global $aArray[2] = [1,2] _ArrayDisplay($aArray, "You've got 5 sec.") _DebugArrayDisplay_TimeoutReturn(0) ; reset to default _ArrayDisplay($aArray, "Wait forever") ConsoleWrite("..the rest of your code" & @CRLF) Disclaimer: "easily patchable code (TM)" is not a trademark of argumentum. Edit: added the code from my next post to remove the timeout by minimizing the ArrayDisplay. Edited September 23 by argumentum updated code for the pause feature Follow the link to my code contribution ( and other things too ). FAQ - Please Read Before Posting. 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