Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation on 07/11/2021 in all areas

  1. During code troubleshooting, the data display functions _ArrayDisplay(), _DebugArrayDisplay() and _WinAPI_DisplayStruct() can be useful to provide a quick visual overview of the contents of arrays and DllStructs. However, these functions each have their own built-in message loop, which will block the code in the main script. In many cases the code in the main script cannot stand to be blocked in this way and will therefore fail. That is, the troubleshooting functions themselves cause an error. And that, of course, isn't an appropriate situation. This example shows how to execute the data display functions in their own processes, to avoid blocking the code in the main script. Other Examples Unblocking a Blocked Message Handler Unblocking a Blocked Message Handler is about several data display functions that mutually block each other, and how to get around this problem. But the example is not about how to avoid the main script from being blocked. In this new example, data display functions will not block each other nor will they block the main script. The IdeaThe main issue in running a data display function in its own process is passing data to the function. The idea is to use a system global ROT object to pass data from the main script to the data display function. The two major advantages of using a ROT object are that it's a very fast data passing method and that the method preserves data types. However, a ROT object can only be used to pass COM compatible data types. An array is such a COM compatible data type (an AutoIt array is not directly COM compatible, but internally it is stored as a safearray of variants that is COM compatible). A DllStruct isn't COM compatible (nor is it processed by internal COM conversions). To pass a DllStruct, we must first convert data to binary data, which is COM compatible. Once the binary data has been passed, it must again be converted back to a DllStruct. The technique is discussed in the DllStruct section of IPC Techniques through ROT Objects. The CodeThe code is implemented as a complete UDF, NonBlockingDataDisplay.au3. The essential code for creating ROT objects is contained in IRunningObjectTable.au3. AccVars.au3 as well as Variant.au3 and SafeArray.au3 contains code to convert a DllStruct to binary data. Two functions at bottom of the new UDF handles the details of DllStruct to binary conversion. RunArrayDisplay() is the UDF function to execute _ArrayDisplay() in a standalone process: Func RunArrayDisplay( _ $sPath, _ ; Path to Includes ended with "\" $aArray, _ $iFlags = 0, _ ; 0 -> 32 bit code, 1 -> 64 bit code $sTitle = "ArrayDisplay", _ $sHeader = Default ) ; Create data transfer object (ROT-object) Local $sDataTransferObject = "DataTransferObject" & ROT_CreateGUID() ROT_RegisterObject( Default, $sDataTransferObject ) ; Default => Object = Dictionary object Local $oDataTransferObject = ObjGet( $sDataTransferObject ) ; Dictionary object ; Add data to transfer object $oDataTransferObject.Add( "$aArray", $aArray ) $oDataTransferObject.Add( "$sTitle", $sTitle ) $oDataTransferObject.Add( "$sHeader", $sHeader ) ; Run _ArrayDisplay() in another process $g_aDataDisplayProgPids[$g_iDataDisplayProgPids] = BitAND( $iFlags, 1 ) _ ? Run( @AutoItExe & " /AutoIt3ExecuteScript " & $sPath & '"RunArrayDisplay64.au3" ' & $sDataTransferObject ) _ ; 64 bit code : Run( @AutoItExe & " /AutoIt3ExecuteScript " & $sPath & '"RunArrayDisplay32.au3" ' & $sDataTransferObject ) ; 32 bit code $g_iDataDisplayProgPids += 1 EndFunc The function executes Includes\RunArrayDisplay64.au3: #AutoIt3Wrapper_UseX64=Y #include <Array.au3> RunDataDisplay() Func RunDataDisplay() ; Get data transfer object Local $sDataTransferObject = $CmdLine[1] ; Get data from transfer object Local $oDataTransferObject = ObjGet( $sDataTransferObject ) Local $aArray = $oDataTransferObject.Item( "$aArray" ) Local $sTitle = $oDataTransferObject.Item( "$sTitle" ) Local $sHeader = $oDataTransferObject.Item( "$sHeader" ) ; Show array _ArrayDisplay( $aArray, $sTitle, "", 0, Default, $sHeader ) EndFunc Examples\RunArrayDisplay64.au3 is the example that demonstrates the use of RunArrayDisplay(). Run the example in SciTE with F5. #AutoIt3Wrapper_Au3Check_Parameters=-d -w- 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=Y Opt( "MustDeclareVars", 1 ) #include "..\Includes\NonBlockingDataDisplay.au3" Example() Func Example() ; Create array Local $aArray[1000][10] For $i = 0 To 1000 - 1 For $j = 0 To 9 $aArray[$i][$j] = $i & "/" & $j Next Next ; Display array RunArrayDisplay( "..\Includes\", $aArray, 1 ) ; 1 -> 64 bit code ; Modify array For $j = 0 To 9 $aArray[0][$j] = "Zero/" & $j Next ; Display array RunArrayDisplay( "..\Includes\", $aArray, 1, "ArrayDisplay 2", "C 0|C 1|C 2|C 3|C 4|C 5|C 6|C 7|C 8|C 9" ) ; The script isn't blocked While Sleep( 1000 ) ConsoleWrite( "The script isn't blocked" & @CRLF ) WEnd EndFunc ExamplesIn the Examples folder, there are three more examples. RunArrayDisplay32.au3 is a 32 bit version of RunArrayDisplay64.au3. RunDebugArrayDisplay64.au3 demonstrates the use of RunDebugArrayDisplay() in the UDF. A prerequisite for running the example is that you're using an AutoIt version that includes _DebugArrayDisplay(). The AutoIt version isn't checked in the code. RunDisplayStruct64.au3 demonstrates the use of RunDisplayStruct() in the UDF. The example is based on the example of _WinAPI_DisplayStruct() in the help file. 7z-fileThe 7z-file contains source code for UDFs and examples. You need AutoIt 3.3.12 or later. Tested on Windows 7 and Windows 10. Comments are welcome. Let me know if there are any issues. NonBlockingDataDisplay.7z
    5 points
  2. Melba23

    AutoIt v3.3.15.4 Beta

    therks, Jon managed to get the known Map bugs fixed in the new Beta and no-one has come up with any new problems of note yet. I think you could safely assume that the functionality will be included in the next release - but as always, no promises. M23
    4 points
  3. Use two parameters for example: _executionFunc($firstValue, $secondValue) and then process both values at the same time within the function. You could also use a flag Basic example (note, don't really understand the need for _ArrayToString, or if you're adding, concatenating data to $collectedDataFromFirstValue) Global $collectedDataFromFirstValue = "" _excutionFunc($firstValue, 1) _excutionFunc($secondValue) Func _excutionFunc($_Value, $_iFlag = 0) Switch $_iFlag Case 1 $collectedDataFromFirstValue &= $_Value Case Else ;~ Do something for other values EndSwitch EndFunc
    1 point
  4. 1> Func _ShowMenu() Local Static $CtMenu ; <-- added GUICtrlDelete($CtMenu) ; <-- added $CtMenu = GUICtrlCreateContextMenu($Button1) $Event = GUICtrlCreateMenuItem(GUICtrlRead($Button1), $CtMenu) GUICtrlSetOnEvent($Event, '_RMenu') EndFunc ;==>_ShowMenu 2> StringFormat("%010s", $iYourNumber) ; <-- formats $iYourNumber as 10 chars with leading zero
    1 point
  5. therks

    AutoIt v3.3.15.4 Beta

    Is there a consensus on the Map variable type? Is it sticking around? I know the help file has the giant experimental feature warning, but it's been a thing for a while and I'm just wondering if there's been any more solid decisions made on whether it's staying or not. I've personally been avoiding it because I didn't want the rug pulled from under me when it gets deprecated. 😅
    1 point
  6. AlexChernavsky, Then you need my StringSize UDF (look in my sig for the link) and a bit of maths: #include <StaticConstants.au3> #include "StringSize.au3" Const $iGUIWidth = 800 Const $iGUIHeight = 200 $hGui = GUICreate("Testing", 800, 200) GUISetFont(20) GUISetState() $hLabelMessage = GUICtrlCreateLabel("Vertically centered", 0, 0, 800, 200, $SS_CENTERIMAGE) Sleep(900) GUICtrlDelete($hLabelMessage) $hLabelMessage = GUICtrlCreateLabel("Horizontally centered", 0, 0, 800, 200, $SS_CENTER) Sleep(900) GUICtrlDelete($hLabelMessage) ; Get the size of label needed to hold the text $aRet = _StringSize("Both vertically" & @CRLF & "and horizontally centered", 20) ; Work out where it needs to be on the GUI $iX = ($iGUIWidth - $aRet[2]) / 2 $iY = ($iGUIHeight - $aRet[3]) / 2 ; And create it $hLabelMessage = GUICtrlCreateLabel("Both vertically" & @CRLF & "and horizontally centered", $iX, $iY, $aRet[2], $aRet[3], $SS_CENTER) Sleep(900)Looks close enough. M23
    1 point
×
×
  • Create New...