LarsJ Posted May 4, 2018 Share Posted May 4, 2018 (edited) Test-00.au3 If you have used ArrayDisplay regularly, you know that it's possible to show more arrays at once in this way (click "Run User Func" button): #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <ArrayDisplay142-1.au3> ShowArray0( 0, 0 ) Func ShowArray0( $p1, $p2 ) Local $aArray0 = [ 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 ] _ArrayDisplay142( $aArray0, "$aArray0", "", 0, Default, Default, Default, Default, ShowArray1 ) #forceref $p1, $p2 EndFunc Func ShowArray1( $p1, $p2 ) Local $aArray1 = [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 11, 12, 13, 14 ] _ArrayDisplay142( $aArray1, "$aArray1", "", 0, Default, Default, Default, Default, ShowArray2 ) #forceref $p1, $p2 EndFunc Func ShowArray2( $p1, $p2 ) Local $aArray2 = [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ] _ArrayDisplay142( $aArray2, "$aArray2", "", 0, Default, Default, Default, Default, ShowArray0 ) #forceref $p1, $p2 EndFunc How does this work? The ArrayDisplay GUI is running in MessageLoop mode. Will the message loop in a later created GUI not block the message loop in a previously created GUI? Yes, it will. But it's important to know exactly what is blocked and what is not blocked. This is the message loop in a slightly modified version of ArrayDisplay from AutoIt 3.3.14.2: expandcollapse popupWhile 1 $iMsg = GUIGetMsg() ; Variable needed to check which "Copy" button was pressed Switch $iMsg Case $idCopy_ID, $idCopy_Data ; Count selected rows Local $iSel_Count = GUICtrlSendMsg($idListView, $LVM_GETSELECTEDCOUNT, 0, 0) ; Display splash dialog if required If $iVerbose And (Not $iSel_Count) And ($iItem_End - $iItem_Start) * ($iSubItem_End - $iSubItem_Start) > 10000 Then SplashTextOn("ArrayDisplay", "Copying data" & @CRLF & @CRLF & "Please be patient", 300, 100) EndIf ; Generate clipboard text Local $sClip = "", $sItem, $aSplit ; Add items For $i = 0 To $iItem_End - $iItem_Start ; Skip if copying selected rows and item not selected If $iSel_Count And Not (GUICtrlSendMsg($idListView, $LVM_GETITEMSTATE, $i, $LVIS_SELECTED)) Then ContinueLoop EndIf $sItem = $avArrayText[$i] If $iMsg = $idCopy_Data Then ; Remove row ID if required $sItem = StringRegExpReplace($sItem, "^\[\d+\].(.*)$", "$1") EndIf If $iCW_ColWidth Then ; Expand columns $aSplit = StringSplit($sItem, $sAD_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, $sAD_Separator, $vUser_Separator) EndIf $sClip &= $sItem & @CRLF Next ; Add header line if required If $iMsg = $idCopy_ID Then If $iCW_ColWidth Then $aSplit = StringSplit($sHeader, $sAD_Separator) $sItem = "" For $j = 1 To $aSplit[0] $sItem &= StringFormat("%-" & $iCW_ColWidth + 1 & "s", StringLeft($aSplit[$j], $iCW_ColWidth)) Next Else $sItem = StringReplace($sHeader, $sAD_Separator, $vUser_Separator) EndIf $sClip = $sItem & @CRLF & $sClip EndIf ;Send to clipboard ClipPut($sClip) ; Remove splash if used SplashOff() ; Refocus ListView GUICtrlSetState($idListView, $GUI_FOCUS) Case $idUser_Func ; Get selected indices Local $aiSelItems[$iRowLimit] = [0] If GUICtrlSendMsg($idListView, $LVM_GETSELECTEDCOUNT, 0, 0) Then For $i = 0 To GUICtrlSendMsg($idListView, $LVM_GETITEMCOUNT, 0, 0) If GUICtrlSendMsg($idListView, $LVM_GETITEMSTATE, $i, $LVIS_SELECTED) Then $aiSelItems[0] += 1 $aiSelItems[$aiSelItems[0]] = $i + $iItem_Start EndIf Next EndIf ReDim $aiSelItems[$aiSelItems[0] + 1] ; Pass array and selection to user function Opt("GUIDataSeparatorChar", $sCurr_Separator) $hUser_Function($aArray, $aiSelItems) Opt("GUIDataSeparatorChar", $sAD_Separator) GUICtrlSetState($idListView, $GUI_FOCUS) Case $idExit_Script ; Clear up GUIDelete($hGUI) Exit Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd And this is the part of the message loop that handles "Run User Func" button clicks: Case $idUser_Func ; Get selected indices Local $aiSelItems[$iRowLimit] = [0] If GUICtrlSendMsg($idListView, $LVM_GETSELECTEDCOUNT, 0, 0) Then For $i = 0 To GUICtrlSendMsg($idListView, $LVM_GETITEMCOUNT, 0, 0) If GUICtrlSendMsg($idListView, $LVM_GETITEMSTATE, $i, $LVIS_SELECTED) Then $aiSelItems[0] += 1 $aiSelItems[$aiSelItems[0]] = $i + $iItem_Start EndIf Next EndIf ReDim $aiSelItems[$aiSelItems[0] + 1] ; Pass array and selection to user function Opt("GUIDataSeparatorChar", $sCurr_Separator) $hUser_Function($aArray, $aiSelItems) ; <<<<<<<< ; The message loop is blocked Opt("GUIDataSeparatorChar", $sAD_Separator) ; until the function returns. GUICtrlSetState($idListView, $GUI_FOCUS) It's the message loop that's blocked. It's blocked by a function that's still running. And which events does this loop handle? It handles button click events and $GUI_EVENT_CLOSE event. So button clicks and $GUI_EVENT_CLOSE does not work. But are there any listview events in the loop? No there are not. Since there are no AutoIt events to handle the listview, the listview is handled entirely through Windows events. And of course Windows events are not blocked. This means that the listview is fully functional. Note that the message loop isn't blocked in the last created GUI. Button clicks and $GUI_EVENT_CLOSE does work in the last created GUI. Is it possible to unblock the blocked message handlers in the ArrayDisplay GUIs that were created before the last GUI? Before we look at ArrayDisplay let's look at some more simple examples. Test-01.au3 Test-01.au3 is similar to Test-00.au3. Only the last created GUI is responsive. The message loop in the other GUIs is blocked. expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <GUIConstantsEx.au3> Opt( "MustDeclareVars", 1 ) Global $aGuiInfo[6+1][2] ; 6 rows for GUIs + 1 row for general info $aGuiInfo[0][0] = 0 ; Current number of GUIs $aGuiInfo[0][1] = 6 ; Max number of GUIs Example() Func Example() ; Max number of GUIs is $aGuiInfo[0][1] If $aGuiInfo[0][0] = $aGuiInfo[0][1] Then Return ; Increase number of GUIs $aGuiInfo[0][0] += 1 ; Find first available index For $iIdx = 1 To $aGuiInfo[0][1] If Not $aGuiInfo[$iIdx][0] Then ExitLoop Next ; Create GUI Local $hGui = GUICreate( "GUI " & $iIdx, 300, 200, 100 + 350 * Mod($iIdx-1,Int($aGuiInfo[0][1]/2)), 100 + 270 * Int(($iIdx-1)/Int($aGuiInfo[0][1]/2)) ) Local $idNew = GUICtrlCreateButton( "Create new GUI", 20, 45, 260, 30 ) Local $idExit = GUICtrlCreateButton( "Exit script", 20, 120, 260, 30 ) ; Store GUI info $aGuiInfo[$iIdx][0] = $iIdx ; Show GUI GUISetState() ; Main loop While 1 Switch GUIGetMsg() Case $idNew Example() Case $idExit Exit Case $GUI_EVENT_CLOSE $aGuiInfo[$iIdx][0] = 0 ; $iIdx $aGuiInfo[0][0] -= 1 ; Decrease number of GUIs ExitLoop EndSwitch WEnd GUIDelete( $hGui ) EndFunc Test-02.au3 Test-02.au3 is a non-blocked version of Test-01.au3: expandcollapse popup#AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <ButtonConstants.au3> #include <MenuConstants.au3> Opt( "MustDeclareVars", 1 ) Global $aGuiInfo[6+1][5] ; 6 rows for GUIs + 1 row for general info $aGuiInfo[0][0] = 0 ; Current number of GUIs $aGuiInfo[0][1] = 6 ; Max number of GUIs ; $aGuiInfo[0][2] = $iIdx, $idNew click event ; $aGuiInfo[0][3] = $iIdx, $idExit click event ; $aGuiInfo[0][4] = $iIdx, $GUI_EVENT_CLOSE, GUI close event ; $aGuiInfo[$iIdx][0] = $iIdx, $iIdx > 0 ; $aGuiInfo[$iIdx][1] = $hGui ; $aGuiInfo[$iIdx][2] = $idNew ; $aGuiInfo[$iIdx][3] = $idExit ; $aGuiInfo[$iIdx][4] = $pMsgHandler Example() Func Example() ; Max number of GUIs is $aGuiInfo[0][1] If $aGuiInfo[0][0] = $aGuiInfo[0][1] Then Return ; Increase number of GUIs $aGuiInfo[0][0] += 1 ; Find first available index For $iIdx = 1 To $aGuiInfo[0][1] If Not $aGuiInfo[$iIdx][0] Then ExitLoop Next ; Create GUI Local $hGui = GUICreate( "GUI " & $iIdx, 300, 200, 100 + 350 * Mod($iIdx-1,Int($aGuiInfo[0][1]/2)), 100 + 270 * Int(($iIdx-1)/Int($aGuiInfo[0][1]/2)) ) Local $idNew = GUICtrlCreateButton( "Create new GUI", 20, 45, 260, 30 ) Local $idExit = GUICtrlCreateButton( "Exit script", 20, 120, 260, 30 ) ; Register non-blocked message handler Local $pMsgHandler = DllCallbackGetPtr( DllCallbackRegister( "MsgHandler", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) DllCall( "comctl32.dll", "bool", "SetWindowSubclass", "hwnd", $hGui, "ptr", $pMsgHandler, "uint_ptr", $iIdx, "dword_ptr", 0 ) ; $iSubclassId = $iIdx, $pData = 0 ; Store GUI info $aGuiInfo[$iIdx][0] = $iIdx $aGuiInfo[$iIdx][1] = $hGui $aGuiInfo[$iIdx][2] = $idNew $aGuiInfo[$iIdx][3] = $idExit $aGuiInfo[$iIdx][4] = $pMsgHandler ; Show GUI GUISetState() ; Main loop While Sleep(10) If $aGuiInfo[0][0] = 0 Then ExitLoop For $iMsg = 2 To 4 If $aGuiInfo[0][$iMsg] Then ExitLoop Next If $iMsg = 5 Then ContinueLoop $iIdx = $aGuiInfo[0][$iMsg] $aGuiInfo[0][$iMsg] = 0 Switch $iMsg ; $idNew click event Case 2 Example() ; $idExit click event Case 3 For $iIdx = 1 To $aGuiInfo[0][1] If Not $aGuiInfo[$iIdx][0] Then ContinueLoop DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aGuiInfo[$iIdx][1], "ptr", $aGuiInfo[$iIdx][4], "uint_ptr", $iIdx ) GUIDelete( $aGuiInfo[$iIdx][1] ) ; GUIDelete( $hGui ) Next Exit ; GUI close event Case 4 DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aGuiInfo[$iIdx][1], "ptr", $aGuiInfo[$iIdx][4], "uint_ptr", $iIdx ) GUIDelete( $aGuiInfo[$iIdx][1] ) ; GUIDelete( $hGui ) $aGuiInfo[$iIdx][0] = 0 ; $iIdx $aGuiInfo[0][0] -= 1 ; Decrease number of GUIs If $aGuiInfo[0][0] = 0 Then ExitLoop EndSwitch WEnd EndFunc Func MsgHandler( $hWnd, $iMsg, $wParam, $lParam, $iIdx, $pData ) ; $iSubclassId = $iIdx If $iMsg <> $WM_COMMAND And $iMsg <> $WM_SYSCOMMAND Then Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] Switch $iMsg Case $WM_COMMAND Switch BitAND( $wParam, 0xFFFF ) ; LoWord Case $aGuiInfo[$iIdx][2] ; $idNew Switch BitShift( $wParam, 16 ) ; HiWord Case $BN_CLICKED $aGuiInfo[0][2] = $iIdx ; $idNew click event EndSwitch Case $aGuiInfo[$iIdx][3] ; $idExit Switch BitShift( $wParam, 16 ) ; HiWord Case $BN_CLICKED $aGuiInfo[0][3] = $iIdx ; $idExit click event EndSwitch EndSwitch Case $WM_SYSCOMMAND Switch $hWnd Case $aGuiInfo[$iIdx][1] ; $hGui Switch $wParam Case $SC_CLOSE $aGuiInfo[0][4] = $iIdx ; GUI close event EndSwitch EndSwitch EndSwitch Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] #forceref $pData EndFunc ; $aGuiInfo[0][2] = $iIdx, $idNew click event ; $aGuiInfo[0][3] = $iIdx, $idExit click event ; $aGuiInfo[0][4] = $iIdx, $GUI_EVENT_CLOSE, GUI close event ; $aGuiInfo[$iIdx][0] = $iIdx, $iIdx > 0 ; $aGuiInfo[$iIdx][1] = $hGui ; $aGuiInfo[$iIdx][2] = $idNew ; $aGuiInfo[$iIdx][3] = $idExit ; $aGuiInfo[$iIdx][4] = $pMsgHandler Note that Test-02.au3 is neither running in MessageLoop Mode (GUIGetMsg isn't called) nor in OnEvent Mode (Opt("GUIOnEventMode", 1) isn't set). Instead, messages are handled through subclassing. And of course, the main loop is still blocked in all GUIs except in the last created GUI. But the chain of GUIs and subclasses means that a message is propagated from one GUI to the next. When the message reaches the last created GUI, where the main loop isn't blocked, the message is handled. The information in the global $aGuiInfo array makes it possible to execute the corresponding code against the proper (active) GUI. Test-03.au3 Test-03.au3 is a non-blocked version of Test-00.au3: #AutoIt3Wrapper_Au3Check_Parameters=-d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 #include <ArrayDisplay142-2.au3> ShowArray0( 0, 0 ) Func ShowArray0( $p1, $p2 ) Local $aArray0 = [ 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 ] _ArrayDisplay142( $aArray0, "$aArray0", "", 0, Default, Default, Default, Default, ShowArray1 ) #forceref $p1, $p2 EndFunc Func ShowArray1( $p1, $p2 ) Local $aArray1 = [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 11, 12, 13, 14 ] _ArrayDisplay142( $aArray1, "$aArray1", "", 0, Default, Default, Default, Default, ShowArray2 ) #forceref $p1, $p2 EndFunc Func ShowArray2( $p1, $p2 ) Local $aArray2 = [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ] _ArrayDisplay142( $aArray2, "$aArray2", "", 0, Default, Default, Default, Default, ShowArray0 ) #forceref $p1, $p2 EndFunc ArrayDisplay142-2.au3 is included instead of ArrayDisplay142-1.au3. After the GUI is created in ArrayDisplay142-2.au3, it's subclassed and information is stored in $aGuiInfo array: ; Register concurrent GUIs ; Increase number of GUIs $aGuiInfo[0][0] += 1 ; Find first available index For $iIdx = 1 To $aGuiInfo[0][1] If Not $aGuiInfo[$iIdx][0] Then ExitLoop Next ; Register non-blocked message handler Local $pMsgHandler = DllCallbackGetPtr( DllCallbackRegister( "MsgHandler", "lresult", "hwnd;uint;wparam;lparam;uint_ptr;dword_ptr" ) ) DllCall( "comctl32.dll", "bool", "SetWindowSubclass", "hwnd", $hGUI, "ptr", $pMsgHandler, "uint_ptr", $iIdx, "dword_ptr", 0 ) ; $iSubclassId = $iIdx, $pData = 0 ; Store GUI info $aGuiInfo[$iIdx][0] = $iIdx $aGuiInfo[$iIdx][1] = $hGUI $aGuiInfo[$iIdx][2] = $idListView $aGuiInfo[$iIdx][3] = $idCopy_ID $aGuiInfo[$iIdx][4] = $idCopy_Data $aGuiInfo[$iIdx][5] = $idUser_Func $aGuiInfo[$iIdx][6] = $idExit_Script $aGuiInfo[$iIdx][7] = $pMsgHandler $aGuiInfo[$iIdx][8] = $avArrayText $aGuiInfo[$iIdx][9] = $aArray $aGuiInfo[$iIdx][10] = $iItem_Start $aGuiInfo[$iIdx][11] = $iItem_End $aGuiInfo[$iIdx][12] = $iSubItem_Start $aGuiInfo[$iIdx][13] = $iSubItem_End $aGuiInfo[$iIdx][14] = $iVerbose $aGuiInfo[$iIdx][15] = $iCW_ColWidth $aGuiInfo[$iIdx][16] = $sHeader $aGuiInfo[$iIdx][17] = $vUser_Separator $aGuiInfo[$iIdx][18] = $hUser_Function This is the new main loop: expandcollapse popupWhile Sleep(10) If $aGuiInfo[0][0] = 0 Then ExitLoop ;$iMsg = GUIGetMsg() ; Variable needed to check which "Copy" button was pressed For $iMsg = 3 To 7 If $aGuiInfo[0][$iMsg] Then ExitLoop Next If $iMsg = 8 Then ContinueLoop $iIdx = $aGuiInfo[0][$iMsg] $aGuiInfo[0][$iMsg] = 0 Switch $iMsg ;Case $idCopy_ID, $idCopy_Data Case 3, 4 $idListView = $aGuiInfo[$iIdx][2] $avArrayText = $aGuiInfo[$iIdx][8] $iItem_Start = $aGuiInfo[$iIdx][10] $iItem_End = $aGuiInfo[$iIdx][11] $iSubItem_Start = $aGuiInfo[$iIdx][12] $iSubItem_End = $aGuiInfo[$iIdx][13] $iVerbose = $aGuiInfo[$iIdx][14] $iCW_ColWidth = $aGuiInfo[$iIdx][15] $sHeader = $aGuiInfo[$iIdx][16] $vUser_Separator = $aGuiInfo[$iIdx][17] ; Count selected rows Local $iSel_Count = GUICtrlSendMsg($idListView, $LVM_GETSELECTEDCOUNT, 0, 0) ; Display splash dialog if required If $iVerbose And (Not $iSel_Count) And ($iItem_End - $iItem_Start) * ($iSubItem_End - $iSubItem_Start) > 10000 Then SplashTextOn("ArrayDisplay", "Copying data" & @CRLF & @CRLF & "Please be patient", 300, 100) EndIf ; Generate clipboard text Local $sClip = "", $sItem, $aSplit ; Add items For $i = 0 To $iItem_End - $iItem_Start ; Skip if copying selected rows and item not selected If $iSel_Count And Not (GUICtrlSendMsg($idListView, $LVM_GETITEMSTATE, $i, $LVIS_SELECTED)) Then ContinueLoop EndIf $sItem = $avArrayText[$i] ;If $iMsg = $idCopy_Data Then If $iMsg = 4 Then ; Remove row ID if required $sItem = StringRegExpReplace($sItem, "^\[\d+\].(.*)$", "$1") EndIf If $iCW_ColWidth Then ; Expand columns $aSplit = StringSplit($sItem, $sAD_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, $sAD_Separator, $vUser_Separator) EndIf $sClip &= $sItem & @CRLF Next ; Add header line if required ;If $iMsg = $idCopy_ID Then If $iMsg = 3 Then If $iCW_ColWidth Then $aSplit = StringSplit($sHeader, $sAD_Separator) $sItem = "" For $j = 1 To $aSplit[0] $sItem &= StringFormat("%-" & $iCW_ColWidth + 1 & "s", StringLeft($aSplit[$j], $iCW_ColWidth)) Next Else $sItem = StringReplace($sHeader, $sAD_Separator, $vUser_Separator) EndIf $sClip = $sItem & @CRLF & $sClip EndIf ;Send to clipboard ClipPut($sClip) ; Remove splash if used SplashOff() ; Refocus ListView GUICtrlSetState($idListView, $GUI_FOCUS) ;Case $idUser_Func Case 5 ; Get selected indices $idListView = $aGuiInfo[$iIdx][2] $iItem_Start = $aGuiInfo[$iIdx][10] Local $aiSelItems[$iRowLimit] = [0] If GUICtrlSendMsg($idListView, $LVM_GETSELECTEDCOUNT, 0, 0) Then For $i = 0 To GUICtrlSendMsg($idListView, $LVM_GETITEMCOUNT, 0, 0) If GUICtrlSendMsg($idListView, $LVM_GETITEMSTATE, $i, $LVIS_SELECTED) Then $aiSelItems[0] += 1 $aiSelItems[$aiSelItems[0]] = $i + $iItem_Start EndIf Next EndIf ReDim $aiSelItems[$aiSelItems[0] + 1] ; Pass array and selection to user function Opt("GUIDataSeparatorChar", $sCurr_Separator) ;$hUser_Function($aArray, $aiSelItems) $aGuiInfo[$iIdx][18]($aGuiInfo[$iIdx][9], $aiSelItems) Opt("GUIDataSeparatorChar", $sAD_Separator) GUICtrlSetState($idListView, $GUI_FOCUS) ;Case $idExit_Script Case 6 ; Clear up For $iIdx = 1 To $aGuiInfo[0][1] If Not $aGuiInfo[$iIdx][0] Then ContinueLoop DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aGuiInfo[$iIdx][1], "ptr", $aGuiInfo[$iIdx][7], "uint_ptr", $iIdx ) GUIDelete( $aGuiInfo[$iIdx][1] ) ; GUIDelete( $hGui ) $aGuiInfo[$iIdx][8] = 0 ; $avArrayText $aGuiInfo[$iIdx][9] = 0 ; $aArray Next Exit ;Case $GUI_EVENT_CLOSE Case 7 DllCall( "comctl32.dll", "bool", "RemoveWindowSubclass", "hwnd", $aGuiInfo[$iIdx][1], "ptr", $aGuiInfo[$iIdx][7], "uint_ptr", $iIdx ) GUIDelete( $aGuiInfo[$iIdx][1] ) ; GUIDelete( $hGui ) $aGuiInfo[$iIdx][8] = 0 ; $avArrayText $aGuiInfo[$iIdx][9] = 0 ; $aArray $aGuiInfo[$iIdx][0] = 0 ; $iIdx $aGuiInfo[0][0] -= 1 ; Decrease number of GUIs If $aGuiInfo[0][0] = 0 Then ExitLoop EndSwitch WEnd And the subclass function: expandcollapse popupFunc MsgHandler( $hWnd, $iMsg, $wParam, $lParam, $iIdx, $pData ) ; $iSubclassId = $iIdx If $iMsg <> $WM_COMMAND And $iMsg <> $WM_SYSCOMMAND Then Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] Switch $iMsg Case $WM_COMMAND Switch BitAND( $wParam, 0xFFFF ) ; LoWord Case $aGuiInfo[$iIdx][3] ; $idCopy_ID Switch BitShift( $wParam, 16 ) ; HiWord Case $BN_CLICKED $aGuiInfo[0][3] = $iIdx ; $idCopy_ID click event EndSwitch Case $aGuiInfo[$iIdx][4] ; $idCopy_Data Switch BitShift( $wParam, 16 ) ; HiWord Case $BN_CLICKED $aGuiInfo[0][4] = $iIdx ; $idCopy_Data click event EndSwitch Case $aGuiInfo[$iIdx][5] ; $idUser_Func Switch BitShift( $wParam, 16 ) ; HiWord Case $BN_CLICKED $aGuiInfo[0][5] = $iIdx ; $idUser_Func click event EndSwitch Case $aGuiInfo[$iIdx][6] ; $idExit_Script Switch BitShift( $wParam, 16 ) ; HiWord Case $BN_CLICKED $aGuiInfo[0][6] = $iIdx ; $idExit_Script click event EndSwitch EndSwitch Case $WM_SYSCOMMAND Switch $hWnd Case $aGuiInfo[$iIdx][1] ; $hGUI Switch $wParam Case $SC_CLOSE $aGuiInfo[0][7] = $iIdx ; GUI close event EndSwitch EndSwitch EndSwitch Return DllCall( "comctl32.dll", "lresult", "DefSubclassProc", "hwnd", $hWnd, "uint", $iMsg, "wparam", $wParam, "lparam", $lParam )[0] #forceref $pData EndFunc Edited September 9, 2018 by LarsJ New zip-file next post Jfish, argumentum, FrancescoDiMuro and 1 other 4 Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions Link to comment Share on other sites More sharing options...
LarsJ Posted September 9, 2018 Author Share Posted September 9, 2018 (edited) In first code box in first post, it's shown how to open three _ArrayDisplays at once. The rest of first post is about how to make all three _ArrayDisplays responsive. But it would be much easier if you could open three _ArrayDisplays at once this way (Test-05.au3): #include <ArrayDisplay142-2.au3> Global $aArray0 = [ 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 ] Global $aArray1 = [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 11, 12, 13, 14 ] Global $aArray2 = [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ] ; Show all three arrays at once _ArrayDisplay142( $aArray0, "$aArray0", "", 128 ) ; 128 => $bMainLoop = False _ArrayDisplay142( $aArray1, "$aArray1", "", 128 ) ; 128 => $bMainLoop = False _ArrayDisplay142( $aArray2, "$aArray2", "", 0 ) ; 0 => $bMainLoop = True It's very very easy. I simply cannot understand why I didn't add the few extra code lines needed, already in first post. The idea is to use a flag value to determine whether the mainloop should run: While $bMainLoop And Sleep(10) ; ... WEnd Default is $bMainLoop = True. What happens if $bMainLoop = False? GUI and ListView have been created before mainloop. In my version of _ArrayDisplay I have carefully ensured that all GUI delete code runs inside the mainloop. If there is no mainloop, GUI and ListView will be created at the start of the function. And then the function ends without the GUI being deleted. In the example, both $aArray0 and $aArray1 are shown without running mainloops, but $aArray2 is shown with a running mainloop to make the GUIs responsive and to ensure that the program doesn't end. Additionally, a little bit of code is added that is executed when $aArray2 is shown. This code sets $bMainLoop = True for $aArray0 and $aArray1, so that one of these GUIs can take over mainloop if $aArray2 GUI is deleted. But by far the majority of this code is already implemented in first post. That's why it's so easy. And of course you can still use code like this (Test-06.au3): #include <ArrayDisplay142-2.au3> Global $aArray0 = [ 00, 01, 02, 03, 04, 05, 06, 07, 08, 09 ] Global $aArray1 = [ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 10, 11, 12, 13, 14 ] Global $aArray2 = [ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 ] ; Show all three arrays at once _ArrayDisplay142( $aArray0, "$aArray0", "", 128, Default, Default, Default, Default, ShowArray1 ) ; 128 => $bMainLoop = False _ArrayDisplay142( $aArray1, "$aArray1", "", 128, Default, Default, Default, Default, ShowArray2 ) ; 128 => $bMainLoop = False _ArrayDisplay142( $aArray2, "$aArray2", "", 0, Default, Default, Default, Default, ShowArray0 ) ; 0 => $bMainLoop = True Func ShowArray0( $p1, $p2 ) _ArrayDisplay142( $aArray0, "$aArray0", "", 0, Default, Default, Default, Default, ShowArray1 ) #forceref $p1, $p2 EndFunc Func ShowArray1( $p1, $p2 ) _ArrayDisplay142( $aArray1, "$aArray1", "", 0, Default, Default, Default, Default, ShowArray2 ) #forceref $p1, $p2 EndFunc Func ShowArray2( $p1, $p2 ) _ArrayDisplay142( $aArray2, "$aArray2", "", 0, Default, Default, Default, Default, ShowArray0 ) #forceref $p1, $p2 EndFunc See example Test-04.au3 to study the code. This is a continuation of Test-02.au3 in the first post. Zip-file The zip-file contains all examples and include files. You need AutoIt 3.3.10 or later. Tested on Windows 10 and Windows 7. Comments are welcome. Let me know if there are any issues. NonBlocked.7z Edited September 9, 2018 by LarsJ Controls, File Explorer, ROT objects, UI Automation, Windows Message MonitorCompiled code: Accessing AutoIt variables, DotNet.au3 UDF, Using C# and VB codeShell menus: The Context menu, The Favorites menu. Shell related: Control Panel, System Image ListsGraphics related: Rubik's Cube, OpenGL without external libraries, Navigating in an image, Non-rectangular selectionsListView controls: Colors and fonts, Multi-line header, Multi-line items, Checkboxes and icons, Incremental searchListView controls: Virtual ListViews, Editing cells, Data display functions 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