Leaderboard
Popular Content
Showing content with the highest reputation since 08/13/2025 in all areas
-
Goal: select the squares to match every row and column results (screenshot below). you can change the puzzle type (addition or multiplication), grid size (3x3 to 9x9), and other preferences. Dependency: this app is also a showcase for the WinPose UDF (which was actually developed for it). Script: #Region wrapper directives #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #AutoIt3Wrapper_UseX64=N #AutoIt3Wrapper_Compile_both=N #AutoIt3Wrapper_Icon=MagicMath.ico #AutoIt3Wrapper_UseUpx=N #AutoIt3Wrapper_Res_Description=Magic Math #AutoIt3Wrapper_Res_Fileversion=1.0.0.0 #AutoIt3Wrapper_Res_ProductVersion=1.0.0.0 #AutoIt3Wrapper_Res_LegalCopyright=Or Ben Shabat (or.ben.shabat@gmail.com) #AutoIt3Wrapper_Run_Au3Stripper=y #Au3Stripper_Parameters=/SO /RM #EndRegion wrapper directives #NoTrayIcon #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <StaticConstants.au3> #include <ColorConstants.au3> #include <FontConstants.au3> #include <AutoItConstants.au3> #include <EditConstants.au3> #include <Math.au3> #include 'WinPose.au3' ; init ; - general Global Const $sAppName = 'Magic Math' ; - colors Global Const $iDefaultSqrSize = 45 Global Const $iDefaultColCount = 5 Global Const $iDefaultRowCount = 5 Global Const $iDefaultResizeSpeed = 50 Global Const $iColor_BoxText = $COLOR_BLACK Global Const $iColor_BoxTextError = $COLOR_RED Global Const $iColor_BoxUnchecked = $COLOR_LIGHTGRAY Global Const $iColor_BoxChecked = $COLOR_LIGHTGREEN Global Const $iColor_BoxEliminated = $COLOR_DARKGRAY Global Const $iColor_BoxResult = $COLOR_PEACHPUFF Global Const $iColor_MenuItem = $COLOR_DARKBLUE Global Const $iColor_MenuItemPressed = $COLOR_LIGHTGRAY Global Const $iColor_MenuItemEmphasis = $COLOR_WHITE Global Const $iColor_Vprimary = $COLOR_LIMEGREEN Global Const $iColor_Vsecondary = $COLOR_AQUA ; - symbols Global Const $symSetup = Chr(64) ; Webdings Global Const $symRenew = Chr(81) ; Wingdings 3 Global Const $symSolve = Chr(97) ; Webdings Global Const $symHelp = Chr(115) ; Webdings Global Const $symP = Chr(200) ; Wingdings 2 Global Const $symX = Chr(208) ; Wingdings 2 Global Const $symV = Chr(252) ; Wingdings ; declare variables Global $bPuzzleTypeIsAddition = True Global $iColCount = $iDefaultColCount, $iRowCount = $iDefaultRowCount, $iSqrSize = $iDefaultSqrSize, $iResizeSpeed = $iDefaultResizeSpeed Global $iGUI_Width, $iGUI_Height, $hGUI Global $aPos, $iWDiff, $iHDiff ; - main GUI Global $gMenu_New, $gMenu_Solve, $gMenu_Pref, $gMenu_Help, $gdGUIStart, $gdGUIEnd, $gdGridStart, $gdGridEnd Global Enum $iGrid_iValue, $iGrid_gID, $iGrid_bSelected, $iGrid_bChecked, $iGrid_bEliminated, $iGrid_iDimCount Global $aGrid[$iColCount][$iRowCount][$iGrid_iDimCount] Global Enum $iResult_iValue, $iResult_iDiff, $iResult_iDimCount Global $aResultOfRow[$iRowCount][$iResult_iDimCount] Global $aResultOfCol[$iColCount][$iResult_iDimCount] Global $gPuzzleType Global $bUserInputAllowed Global $bCheckForVictory ; - pref GUI Global $gPuzzleType_Addition, $gPuzzleType_Multiplication, _ $gGridWidth_Down, $gGridWidth_Data, $gGridWidth_Up, _ $gGridHeight_Down, $gGridHeight_Data, $gGridHeight_Up, _ $gSqrSize_Down, $gSqrSize_Data, $gSqrSize_Up, _ $gResizeSpeed_data, _ $gOK ; GUI $iGUI_Width = $iSqrSize * ($iColCount + 3) + 2 $iGUI_Height = $iSqrSize * ($iRowCount + 2) + 2 $hGUI = GUICreate($sAppName, $iGUI_Width, $iGUI_Height) $aPos = WinGetPos($hGUI) $iWDiff = $aPos[2] - $iGUI_Width $iHDiff = $aPos[3] - $iGUI_Height BuildGUI() GUISetState(@SW_SHOW, $hGUI) ; main loop Global $msg Global $aCursorInfo $bCheckForVictory = False While True $msg = GUIGetMsg() Switch $msg Case $gMenu_New GUICtrlSetBkColor($gMenu_New, $iColor_MenuItemPressed) Sleep(100) Renew() Sleep(100) GUICtrlSetBkColor($gMenu_New, $GUI_BKCOLOR_TRANSPARENT) Case $gMenu_Solve GUICtrlSetBkColor($gMenu_Solve, $iColor_MenuItemPressed) Sleep(100) Solve() Sleep(100) GUICtrlSetBkColor($gMenu_Solve, $GUI_BKCOLOR_TRANSPARENT) Case $gMenu_Pref GUICtrlSetBkColor($gMenu_Pref, $iColor_MenuItemPressed) Sleep(100) BuildGUI(Pref()) Sleep(100) GUICtrlSetBkColor($gMenu_Pref, $GUI_BKCOLOR_TRANSPARENT) Case $gMenu_Help GUICtrlSetBkColor($gMenu_Help, $iColor_MenuItemPressed) Sleep(100) BuildGUI(Help()) Sleep(100) GUICtrlSetBkColor($gMenu_Help, $GUI_BKCOLOR_TRANSPARENT) Case $gdGridStart To $gdGridEnd If $bUserInputAllowed Then For $iRow = 0 To $iRowCount - 1 For $iCol = 0 To $iColCount - 1 If $msg = $aGrid[$iCol][$iRow][$iGrid_gID] Then $aGrid[$iCol][$iRow][$iGrid_bEliminated] = False $aGrid[$iCol][$iRow][$iGrid_bChecked] = Not $aGrid[$iCol][$iRow][$iGrid_bChecked] GUICtrlSetBkColor($aGrid[$iCol][$iRow][$iGrid_gID], $aGrid[$iCol][$iRow][$iGrid_bChecked] ? $iColor_BoxChecked : $iColor_BoxUnchecked) EndIf Next Next $bCheckForVictory = True EndIf Case $GUI_EVENT_SECONDARYUP $aCursorInfo = GUIGetCursorInfo() If $aCursorInfo[4] > $gdGridStart And $aCursorInfo[4] < $gdGridEnd Then If $bUserInputAllowed Then For $iRow = 0 To $iRowCount - 1 For $iCol = 0 To $iColCount - 1 If $aCursorInfo[4] = $aGrid[$iCol][$iRow][$iGrid_gID] Then $aGrid[$iCol][$iRow][$iGrid_bChecked] = False $aGrid[$iCol][$iRow][$iGrid_bEliminated] = Not $aGrid[$iCol][$iRow][$iGrid_bEliminated] GUICtrlSetBkColor($aGrid[$iCol][$iRow][$iGrid_gID], $aGrid[$iCol][$iRow][$iGrid_bEliminated] ? $iColor_BoxEliminated : $iColor_BoxUnchecked) EndIf Next Next $bCheckForVictory = True EndIf EndIf Case $GUI_EVENT_CLOSE ExitLoop EndSwitch If $bCheckForVictory Then If IsVictoryAchieved() Then ShowVictory() GUICtrlSetBkColor($gMenu_New, $iColor_MenuItemEmphasis) Sleep(125) Renew() Sleep(125) GUICtrlSetBkColor($gMenu_New, $GUI_BKCOLOR_TRANSPARENT) EndIf $bCheckForVictory = False EndIf WEnd Func Renew($bNew = True) $bUserInputAllowed = True Local $bNoZeroResults GUISetState(@SW_LOCK) Do $bNoZeroResults = True For $iRow = 0 To $iRowCount - 1 For $iCol = 0 To $iColCount - 1 If $bNew Then $aGrid[$iCol][$iRow][$iGrid_iValue] = $bPuzzleTypeIsAddition ? Random(1, 9, 1) : Random(2, 9, 1) $aGrid[$iCol][$iRow][$iGrid_bSelected] = (Random() < 0.5) $aGrid[$iCol][$iRow][$iGrid_bChecked] = False $aGrid[$iCol][$iRow][$iGrid_bEliminated] = False EndIf GUICtrlSetData($aGrid[$iCol][$iRow][$iGrid_gID], $aGrid[$iCol][$iRow][$iGrid_iValue]) GUICtrlSetColor($aGrid[$iCol][$iRow][$iGrid_gID], $iColor_BoxText) Select Case $aGrid[$iCol][$iRow][$iGrid_bChecked] GUICtrlSetBkColor($aGrid[$iCol][$iRow][$iGrid_gID], $iColor_BoxChecked) Case $aGrid[$iCol][$iRow][$iGrid_bEliminated] GUICtrlSetBkColor($aGrid[$iCol][$iRow][$iGrid_gID], $iColor_BoxEliminated) Case Else GUICtrlSetBkColor($aGrid[$iCol][$iRow][$iGrid_gID], $iColor_BoxUnchecked) EndSelect GUICtrlSetCursor($aGrid[$iCol][$iRow][$iGrid_gID], $MCID_ARROW) Next Next Local $iResult For $iRow = 0 To $iRowCount - 1 $iResult = 0 For $iCol = 0 To $iColCount - 1 If $aGrid[$iCol][$iRow][$iGrid_bSelected] Then $iResult = Accumulate($iResult, $aGrid[$iCol][$iRow][$iGrid_iValue]) Next If $iResult = 0 Then $bNoZeroResults = False GUICtrlSetData($aResultOfRow[$iRow][$iResult_iValue], $iResult) GUICtrlSetFont($aResultOfRow[$iRow][$iResult_iValue], _Min($iSqrSize / 3, $iSqrSize / StringLen($iResult))) Next For $iCol = 0 To $iColCount - 1 $iResult = 0 For $iRow = 0 To $iRowCount - 1 If $aGrid[$iCol][$iRow][$iGrid_bSelected] Then $iResult = Accumulate($iResult, $aGrid[$iCol][$iRow][$iGrid_iValue]) Next If $iResult = 0 Then $bNoZeroResults = False GUICtrlSetData($aResultOfCol[$iCol][$iResult_iValue], $iResult) GUICtrlSetFont($aResultOfCol[$iCol][$iResult_iValue], _Min($iSqrSize / 3, $iSqrSize / StringLen($iResult))) Next Until $bNoZeroResults GUISetState(@SW_UNLOCK) EndFunc ;==>Renew Func Accumulate(ByRef $iBase, $iDelta) If $iBase = 0 Then Return $iDelta If $bPuzzleTypeIsAddition Then Return $iBase + $iDelta Else Return $iBase * $iDelta EndIf EndFunc ;==>Accumulate Func Solve() $bUserInputAllowed = False For $iRow = 0 To $iRowCount - 1 For $iCol = 0 To $iColCount - 1 GUICtrlSetBkColor($aGrid[$iCol][$iRow][$iGrid_gID], $aGrid[$iCol][$iRow][$iGrid_bSelected] ? $iColor_BoxChecked : $iColor_BoxEliminated) If $aGrid[$iCol][$iRow][$iGrid_bSelected] <> $aGrid[$iCol][$iRow][$iGrid_bChecked] Then GUICtrlSetColor($aGrid[$iCol][$iRow][$iGrid_gID], $iColor_BoxTextError) GUICtrlSetCursor($aGrid[$iCol][$iRow][$iGrid_gID], $MCID_NO) Next Next EndFunc ;==>Solve Func IsVictoryAchieved() Local $iResult For $iRow = 0 To $iRowCount - 1 $iResult = 0 For $iCol = 0 To $iColCount - 1 If $aGrid[$iCol][$iRow][$iGrid_bChecked] Then $iResult = Accumulate($iResult, $aGrid[$iCol][$iRow][$iGrid_iValue]) Next If GUICtrlRead($aResultOfRow[$iRow][$iResult_iValue]) <> $iResult Then Return False Next For $iCol = 0 To $iColCount - 1 $iResult = 0 For $iRow = 0 To $iRowCount - 1 If $aGrid[$iCol][$iRow][$iGrid_bChecked] Then $iResult = Accumulate($iResult, $aGrid[$iCol][$iRow][$iGrid_iValue]) Next If GUICtrlRead($aResultOfCol[$iCol][$iResult_iValue]) <> $iResult Then Return False Next Return True EndFunc ;==>IsVictoryAchieved Func ShowVictory() Sleep(150) Local $gV = GUICtrlCreateLabel($symV, 0, 0, $iGUI_Width, $iGUI_Height, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont($gV, _Min($iGUI_Height, $iGUI_Width) * 0.6, Default, Default, 'Wingdings') GUICtrlSetBkColor($gV, $GUI_BKCOLOR_TRANSPARENT) GUICtrlSetColor($gV, $iColor_Vprimary) For $i = 1 To 2 Sleep(125) GUICtrlSetColor($gV, $iColor_Vsecondary) Sleep(125) GUICtrlSetColor($gV, $iColor_Vprimary) Next Sleep(1000) GUICtrlDelete($gV) Sleep(250) EndFunc ;==>ShowVictory Func BuildGUI($bNew = True) GUISetFont($iSqrSize / 3, Default, Default, 'Tahoma') ; GUI contents $gdGUIStart = GUICtrlCreateDummy() ; - menu $gMenu_Pref = GUICtrlCreateLabel($symSetup, 1, 1 + $iSqrSize / 2, $iSqrSize * 1.5 - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetTip(-1, 'Set your preferences and construct a new puzzle', 'Setup') GUICtrlSetFont(-1, $iSqrSize / 2, Default, Default, 'Webdings') GUICtrlSetColor(-1, $iColor_MenuItem) GUICtrlSetCursor(-1, $MCID_HAND) $gMenu_New = GUICtrlCreateLabel($symRenew, 1, $iSqrSize + 1 + $iSqrSize / 2, $iSqrSize * 1.5 - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetTip(-1, 'Construct a new puzzle using current preferences', 'New Puzzle') GUICtrlSetFont(-1, $iSqrSize / 2, Default, Default, 'Wingdings 3') GUICtrlSetColor(-1, $iColor_MenuItem) GUICtrlSetCursor(-1, $MCID_HAND) $gMenu_Solve = GUICtrlCreateLabel($symV, 1, $iSqrSize * 2 + 1 + $iSqrSize / 2, $iSqrSize * 1.5 - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetTip(-1, 'I give up :(', 'Show Solution') GUICtrlSetFont(-1, $iSqrSize / 2, Default, Default, 'Wingdings') GUICtrlSetColor(-1, $iColor_MenuItem) GUICtrlSetCursor(-1, $MCID_HAND) $gMenu_Help = GUICtrlCreateLabel($symHelp, 1, $iSqrSize * 3 + 1 + $iSqrSize / 2, $iSqrSize * 1.5 - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetTip(-1, 'What do I do here?', 'Instructions') GUICtrlSetFont(-1, $iSqrSize / 2, Default, Default, 'Webdings') GUICtrlSetColor(-1, $iColor_MenuItem) GUICtrlSetCursor(-1, $MCID_HAND) ; - grid ; -- center part ReDim $aGrid[$iColCount][$iRowCount][$iGrid_iDimCount] $gdGridStart = GUICtrlCreateDummy() For $iRow = 0 To $iRowCount - 1 For $iCol = 0 To $iColCount - 1 $aGrid[$iCol][$iRow][$iGrid_gID] = GUICtrlCreateLabel('', ($iCol + 1) * $iSqrSize + 2 + $iSqrSize / 2, $iRow * $iSqrSize + 2 + $iSqrSize / 2, $iSqrSize - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) Next Next $gdGridEnd = GUICtrlCreateDummy() ; -- results of rows ReDim $aResultOfRow[$iRowCount][$iResult_iDimCount] For $iRow = 0 To $iRowCount - 1 $aResultOfRow[$iRow][$iResult_iValue] = GUICtrlCreateLabel('', ($iColCount + 1) * $iSqrSize + 2 + $iSqrSize / 2, $iRow * $iSqrSize + 2 + $iSqrSize / 2, $iSqrSize - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, $iColor_BoxResult) Next ; -- results of cols ReDim $aResultOfCol[$iColCount][$iResult_iDimCount] For $iCol = 0 To $iColCount - 1 $aResultOfCol[$iCol][$iResult_iValue] = GUICtrlCreateLabel('', ($iCol + 1) * $iSqrSize + 2 + $iSqrSize / 2, $iRowCount * $iSqrSize + 2 + $iSqrSize / 2, $iSqrSize - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, $iColor_BoxResult) Next ; -- puzzle type GUICtrlCreateLabel($bPuzzleTypeIsAddition ? $symP : $symX, ($iColCount + 1) * $iSqrSize + 2 + $iSqrSize / 2, $iRowCount * $iSqrSize + 2 + $iSqrSize / 2, $iSqrSize - 2, $iSqrSize - 2, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, Default, Default, Default, 'Wingdings 2') GUICtrlSetBkColor(-1, $iColor_MenuItemEmphasis) GUICtrlSetTip(-1, ($bPuzzleTypeIsAddition ? 'Addition' : 'Multplication'), 'Puzzle Type:') ; - populate grid Renew($bNew) ; finalize GUI $gdGUIEnd = GUICtrlCreateDummy() EndFunc ;==>BuildGUI Func Pref() Local Const $iSUI_W = 200, $iSUI_H = 280, $iSUI_ButtonH = 30, $iSUI_ButtonSpacing = 10 GUISetFont(9.5, Default, Default, 'Tahoma') Local $x = 10, $y = 10, $dy = 25 ; delete all controls DeleteAllControls() ; resize GUI WinSetTrans($hGUI, '', 192) WinSetTitle($hGUI, '', $sAppName & ' Setup') _WinPoseAroundCenter($hGUI, $iSUI_W + $iWDiff, $iSUI_H + $iHDiff, $iResizeSpeed) WinSetTrans($hGUI, '', 255) ; generate controls $gdGUIStart = GUICtrlCreateDummy() GUICtrlCreateLabel('Puzzle', $x, $y, 85, Default, $SS_CENTERIMAGE) GUICtrlSetFont(-1, Default, 600) $x += 5 $y += $dy GUICtrlCreateLabel('Puzzle Type:', $x, $y, 80, Default, $SS_CENTERIMAGE) $x += 90 $gPuzzleType_Addition = GUICtrlCreateLabel($symP, $x, $y, 41, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 12, Default, Default, 'Wingdings 2') $x += 42 $gPuzzleType_Multiplication = GUICtrlCreateLabel($symX, $x, $y, 41, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 12, Default, Default, 'Wingdings 2') Pref_RefreshPuzzleTypeButtons($gPuzzleType_Addition, $gPuzzleType_Multiplication) $x -= 42 $x -= 90 $y += $dy GUICtrlCreateLabel('Columns:', $x, $y, 80, Default, $SS_CENTERIMAGE) $x += 90 $gGridWidth_Down = GUICtrlCreateLabel('-', $x, $y, 23, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13, 800) GUICtrlSetBkColor(-1, $COLOR_LIGHTGRAY) GUICtrlSetCursor(-1, $MCID_HAND) $x += 25 $gGridWidth_Data = GUICtrlCreateLabel($iColCount, $x, $y, 33, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, $COLOR_LIGHTBLUE) $x += 35 $gGridWidth_Up = GUICtrlCreateLabel('+', $x, $y, 23, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13, 800) GUICtrlSetBkColor(-1, $COLOR_LIGHTGRAY) GUICtrlSetCursor(-1, $MCID_HAND) $x -= 35 $x -= 25 $x -= 90 $y += $dy GUICtrlCreateLabel('Rows:', $x, $y, Default, Default, $SS_CENTERIMAGE) $x += 90 $gGridHeight_Down = GUICtrlCreateLabel('-', $x, $y, 23, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13, 800) GUICtrlSetBkColor(-1, $COLOR_LIGHTGRAY) GUICtrlSetCursor(-1, $MCID_HAND) $x += 25 $gGridHeight_Data = GUICtrlCreateLabel($iRowCount, $x, $y, 33, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, $COLOR_LIGHTBLUE) $x += 35 $gGridHeight_Up = GUICtrlCreateLabel('+', $x, $y, 23, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13, 800) GUICtrlSetBkColor(-1, $COLOR_LIGHTGRAY) GUICtrlSetCursor(-1, $MCID_HAND) $x -= 35 $x -= 25 $x -= 90 $y += $dy $x -= 5 $y += $dy GUICtrlCreateLabel('Appearance', $x, $y, 85, Default, $SS_CENTERIMAGE) GUICtrlSetFont(-1, Default, 600) $y += $dy $x += 5 GUICtrlCreateLabel('Square Size:', $x, $y, Default, Default, $SS_CENTERIMAGE) $x += 90 $gSqrSize_Down = GUICtrlCreateLabel('-', $x, $y, 23, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13, 800) GUICtrlSetBkColor(-1, $COLOR_LIGHTGRAY) GUICtrlSetCursor(-1, $MCID_HAND) $x += 25 $gSqrSize_Data = GUICtrlCreateLabel($iSqrSize, $x, $y, 33, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetBkColor(-1, $COLOR_LIGHTBLUE) $x += 35 $gSqrSize_Up = GUICtrlCreateLabel('+', $x, $y, 23, 22, BitOR($SS_CENTER, $SS_CENTERIMAGE)) GUICtrlSetFont(-1, 13, 800) GUICtrlSetBkColor(-1, $COLOR_LIGHTGRAY) GUICtrlSetCursor(-1, $MCID_HAND) $x -= 35 $x -= 25 $x -= 90 $y += $dy GUICtrlCreateLabel('Resize speed:', $x, $y, Default, Default, $SS_CENTERIMAGE) $x += 90 $gResizeSpeed_data = GUICtrlCreateSlider($x, $y, 80) GUICtrlSetLimit(-1, 100) GUICtrlSetData(-1, $iResizeSpeed) $x -= 90 #cs FUTURE DEVELOPMENT ----- BUILD PHASE: allow zero sum/prod use 8 & 9 in multiplication puzzle (HARDER) increase/decrease target squares count (determine probability of a square to participate) allow negative numbers (HARDER) ----- GAME PHASE: show target squares count show current/target squares count allow marking cols & rows as balanced automatically mark cols & rows as balanced automatically mark invalid selection (div creating mod, sum/prod exceeding result) show diff calc allow hints allow real-time switch puzzle type #ce Local $gOK = GUICtrlCreateButton('Done', $iSUI_ButtonSpacing, $iSUI_H - $iSUI_ButtonH - $iSUI_ButtonSpacing, $iSUI_W - $iSUI_ButtonSpacing * 2, $iSUI_ButtonH) $gdGUIEnd = GUICtrlCreateDummy() ; user interaction While True $msg = GUIGetMsg() Switch $msg Case $gPuzzleType_Addition If Not $bPuzzleTypeIsAddition Then $bPuzzleTypeIsAddition = True Pref_RefreshPuzzleTypeButtons($gPuzzleType_Addition, $gPuzzleType_Multiplication) EndIf Case $gPuzzleType_Multiplication If $bPuzzleTypeIsAddition Then $bPuzzleTypeIsAddition = False Pref_RefreshPuzzleTypeButtons($gPuzzleType_Addition, $gPuzzleType_Multiplication) EndIf Case $gGridWidth_Up $iColCount = _Min($iColCount + 1, 9) GUICtrlSetData($gGridWidth_Data, $iColCount) Case $gGridWidth_Down $iColCount = _Max($iColCount - 1, 3) GUICtrlSetData($gGridWidth_Data, $iColCount) Case $gGridHeight_Up $iRowCount = _Min($iRowCount + 1, 9) GUICtrlSetData($gGridHeight_Data, $iRowCount) Case $gGridHeight_Down $iRowCount = _Max($iRowCount - 1, 3) GUICtrlSetData($gGridHeight_Data, $iRowCount) Case $gSqrSize_Up $iSqrSize = _Min($iSqrSize + 5, 60) GUICtrlSetData($gSqrSize_Data, $iSqrSize) Case $gSqrSize_Down $iSqrSize = _Max($iSqrSize - 5, 20) GUICtrlSetData($gSqrSize_Data, $iSqrSize) Case $gOK, $GUI_EVENT_CLOSE $iResizeSpeed = GUICtrlRead($gResizeSpeed_data) ExitLoop EndSwitch WEnd ; delete all controls DeleteAllControls() ; - resize GUI WinSetTrans($hGUI, '', 192) WinSetTitle($hGUI, '', $sAppName) $iGUI_Width = $iSqrSize * ($iColCount + 3) + 2 $iGUI_Height = $iSqrSize * ($iRowCount + 2) + 2 _WinPoseAroundCenter($hGUI, $iGUI_Width + $iWDiff, $iGUI_Height + $iHDiff, $iResizeSpeed) WinSetTrans($hGUI, '', 255) Return True EndFunc ;==>Pref Func Pref_RefreshPuzzleTypeButtons($gPuzzleType_Addition, $gPuzzleType_Multiplication) GUICtrlSetBkColor($gPuzzleType_Addition, $bPuzzleTypeIsAddition ? $COLOR_LIGHTBLUE : $COLOR_LIGHTGRAY) GUICtrlSetCursor($gPuzzleType_Addition, $bPuzzleTypeIsAddition ? $MCID_ARROW : $MCID_HAND) GUICtrlSetBkColor($gPuzzleType_Multiplication, $bPuzzleTypeIsAddition ? $COLOR_LIGHTGRAY : $COLOR_LIGHTBLUE) GUICtrlSetCursor($gPuzzleType_Multiplication, $bPuzzleTypeIsAddition ? $MCID_HAND : $MCID_ARROW) EndFunc ;==>Pref_RefreshPuzzleTypeButtons Func Help() Local Const $iSUI_W = 410, $iSUI_H = 350, $iSUI_ButtonH = 30, $iSUI_ButtonSpacing = 10 GUISetFont(9.5, Default, Default, 'Tahoma') Local $x = 15, $y = 10, $dy = 25 ; delete all controls DeleteAllControls() ; resize GUI WinSetTrans($hGUI, '', 192) WinSetTitle($hGUI, '', $sAppName & ' Instructions') _WinPoseAroundCenter($hGUI, $iSUI_W + $iWDiff, $iSUI_H + $iHDiff, $iResizeSpeed) WinSetTrans($hGUI, '', 255) ; generate controls $gdGUIStart = GUICtrlCreateDummy() GUICtrlCreateLabel('WARNING! This game may be highly addictive :-)' & @CRLF & @CRLF & _ 'Click the gray squares in the middle to select them and paint them green. The selected squares in every row must match the result of the row, displayed on the right-hand side; the selected squares in every column must match the result of the column, displayed at the bottom.' & @CRLF & @CRLF & _ 'If you eliminate a square, you may right-click it to paint it dark gray.' & @CRLF & @CRLF & _ 'The type of the puzzle - Addition or Multiplication - is indicated in the white square at the bottom-right corner.' & @CRLF & @CRLF & _ 'Click the "Tools" icon on the upper-left corner to change puzzle type, grid size and other preferences.' & @CRLF & @CRLF & _ 'Enjoy :-)', $x, $y, $iSUI_W - $x * 2, $iSUI_H - 60) $y += $dy $gOK = GUICtrlCreateButton('OK, I think I got it...', $iSUI_ButtonSpacing, $iSUI_H - $iSUI_ButtonH - $iSUI_ButtonSpacing, $iSUI_W - $iSUI_ButtonSpacing * 2, $iSUI_ButtonH) $gdGUIEnd = GUICtrlCreateDummy() ; user interaction While True $msg = GUIGetMsg() Switch $msg Case $gOK, $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd ; delete all controls DeleteAllControls() ; resize GUI WinSetTrans($hGUI, '', 192) WinSetTitle($hGUI, '', $sAppName) _WinPoseAroundCenter($hGUI, $iGUI_Width + $iWDiff, $iGUI_Height + $iHDiff, $iResizeSpeed) WinSetTrans($hGUI, '', 255) Return False EndFunc ;==>Help Func GuiCtrlDeleteAndZero(ByRef $gID) If GUICtrlDelete($gID) Then $gID = 0 Return 1 Else Return 0 EndIf EndFunc ;==>GuiCtrlDeleteAndZero Func DeleteAllControls() Local $gIDStart = $gdGUIStart Local $gIDEnd = $gdGUIEnd For $gID = $gIDStart To $gIDEnd GuiCtrlDeleteAndZero($gID) Next EndFunc ;==>DeleteAllControls Func _WinPoseAroundCenter($hGUI, $iNewWidth, $iNewHeight, $iSpeed = 0) Local $aPos = WinGetPos($hGUI) Local $x = $aPos[0] + $aPos[2] / 2 - $iNewWidth / 2 If $x < 0 Then $x = 0 If $x + $iNewWidth > @DesktopWidth Then $x = @DesktopWidth - $iNewWidth Local $y = $aPos[1] + $aPos[3] / 2 - $iNewHeight / 2 If $y < 0 Then $y = 0 If $y + $iNewHeight > @DesktopHeight Then $y = @DesktopHeight - $iNewHeight _WinPose($hGUI, '', $x, $y, $iNewWidth, $iNewHeight, $iSpeed) EndFunc ;==>_WinPoseAroundCenter enjoy! MagicMath.ico5 points
-
JSON UDF in pure AutoIt
ioa747 and 3 others reacted to AspirinJunkie for a topic
There is a new version. This brings a significant performance increase. In my tests, _JSON_Parse() is now around 40–55% faster, and for _JSON_Generate(), the increase is around 15–35%. I didn't thought there was still such potential in the code. However, I still had a few ideas in mind that required quite a bit of restructuring, but I've now tackled them accordingly. In my opinion, it was worth it. In the process, I removed ByRef everywhere, so that direct value transfer is now possible for all functions (which was a request). I also added notes on how to handle .json files to the Readme.md (@WildByDesign: I hope that was what you meant?).4 points -
Brief: native WinMove() has a "speed" parameter for a more fluent movement. unfortunately, that applies to the change in position, but not the change in size. the position changes in the specified "speed", but size changes abruptly. _WinPose() is similar to WinMove(), except that move and resize are simultaneous, both conform to the speed parameter. UDF: (save as "WinPose.au3") #include-once #include <WinAPISysWin.au3> ; #FUNCTION# ==================================================================================================================== ; Name ..........: _WinPose ; Description ...: same as native WinMove(), except that move and resize are simultaneous, both conform to the speed parameter. ; Syntax ........: _WinPose($hWnd, $sText, $x, $y, $w, $h[, $speed = 0]) ; Parameters ....: $hWnd - the title/hWnd/class of the window to pose. ; $sText - the text of the window to pose. ; $x - X coordinate to move to. ; $y - Y coordinate to move to. ; $w - [optional] new width of the window. ; $h - [optional] new height of the window. ; $speed - [optional] the speed to pose the window (smaller value = faster speed, 0 = instantaneous). ; Return values .: Success - a handle to the window. ; Failure - 0 if the window is not found (also sets @error to non-zero). ; Author ........: orbs ; Modified ......: ; Remarks .......: parameters and return values are practically identical to those of the native WinMove() function. ; Related .......: ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _WinPose($hWnd, $sText, $x, $y, $w = Default, $h = Default, $speed = 0) ; find the window to move If Not IsHWnd($hWnd) Then $hWnd = WinGetHandle($hWnd, $sText) If @error Then Return SetError(1, 0, False) EndIf Local $aPos = WinGetPos($hWnd) If @error Then Return SetError(2, 0, False) ; initialize variables Local Enum $pos_x, $pos_y, $pos_w, $pos_h Local Enum $aiCurrent, $aiTarget, $aiDelta, $aiRatio Local $aPosTarget[4][4] = [[$aPos[$pos_x], $x, 0, 0], [$aPos[$pos_y], $y, 0, 0], [$aPos[$pos_w], $w, 0, 0], [$aPos[$pos_h], $h, 0, 0]] ; accomodate for Default keyword For $iElement = 0 To 3 If $aPosTarget[$iElement][$aiTarget] = Default Then $aPosTarget[$iElement][$aiTarget] = $aPos[$iElement] Next ; calculate delta For $iElement = 0 To 3 $aPosTarget[$iElement][$aiDelta] = $aPosTarget[$iElement][$aiTarget] - $aPosTarget[$iElement][$aiCurrent] Next ; find the maximum delta Local $iMaxElement = 0, $iMaxDelta = 0 For $iElement = 0 To 3 If Abs($aPosTarget[$iElement][$aiDelta]) > $iMaxDelta Then $iMaxElement = $iElement $iMaxDelta = $aPosTarget[$iElement][$aiDelta] EndIf Next ; accomodate for negative delta If ($aPosTarget[$iMaxElement][$aiTarget] - $aPos[$iMaxElement]) < 0 Then $iMaxDelta = -$iMaxDelta ; calculate ratio for all elements For $iElement = 0 To 3 $aPosTarget[$iElement][$aiRatio] = $aPosTarget[$iElement][$aiDelta] / $iMaxDelta Next ; move & resize the window gradually For $iStep = 0 To $iMaxDelta For $iElement = 0 To 3 $aPosTarget[$iElement][$aiCurrent] += $aPosTarget[$iElement][$aiRatio] Next For $i = 1 To $speed _WinAPI_MoveWindow($hWnd, _ $aPosTarget[$pos_x][$aiCurrent], _ $aPosTarget[$pos_y][$aiCurrent], _ $aPosTarget[$pos_w][$aiCurrent], _ $aPosTarget[$pos_h][$aiCurrent], False) Next Next ; validate final outcome is as expected Return WinMove($hWnd, '', $x, $y, $w, $h) EndFunc ;==>_WinPose Example: #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 5 -w 6 -w 7 #include <AutoItConstants.au3> #include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include 'WinPose.au3' Global Const $iMinW = 250, $iMinH = 100 Global $x, $y, $w, $h, $speed Global $hGUI = GUICreate('_WinPose() Example', $iMinW, $iMinH) Global $gButton = GUICtrlCreateButton('Click Me!', 25, 25, 200, 50) GUICtrlSetResizing(-1, $GUI_DOCKBORDERS) GUISetState(@SW_SHOW) Global $msg While True $msg = GUIGetMsg() Switch $msg Case $GUI_EVENT_CLOSE ExitLoop Case $gButton $w = Random($iMinW, @DesktopWidth / 3, 1) $h = Random($iMinH, @DesktopHeight / 3, 1) $x = Random(0, @DesktopWidth - $w, 1) $y = Random(0, @DesktopHeight - $h, 1) $speed = Random(10, 100, 1) _WinPose($hGUI, '', $x, $y, $w, $h, $speed) EndSwitch WEnd click the button to pose the window in a new random position and size, in a random speed. enjoy 🙂3 points
-
Hi guys, apologies in advance for the wall of text! Just an update as to where things are ATM - I've have gone on a tangent re: resolving IIDs for paramatised interfaces. This is more of a core WinRT thing - but I thought I'd take whoever is interested along on the ride... So I attempted to create a grid (Microsoft.UI.Xaml.Controls.Grid) which should theoretically allows us drop other controls within it. Basically its a layout thing to divide up the window. Want an "OK" button down the bottom right? Just nest the button in the cell that is down there!. Creating a grid, then extracting the row and column definitions is easy enough. #include "Include\Classes\Microsoft.UI.Xaml.Controls.Grid.au3" ;-- Setup window etc. -- Local $pGrid_Fact = _WinRT_GetActivationFactory("Microsoft.UI.Xaml.Controls.Grid", $sIID_IGridFactory) Local $pGrid = IGridFactory_CreateInstance($pGrid_Fact, 0, $pInner) Local $pColDefs = IGrid_GetColumnDefinitions($pGrid) Local $pRowDefs = IGrid_GetRowDefinitions($pGrid) Looking at $pColDefs, we can determine its a "Microsoft.UI.Xaml.Controls.ColumnDefinitionCollection". We know this by inspecting Microsoft.UI.Xaml.Controls.Grid in the class explorer. Otherwise _WinRT_DisplayInterfaces($pColDefs ) or _WinRT_DisplayClass($pColDefs ) will get you to the same place. Method : get_ColumnDefinitions Fn : value = get_ColumnDefinitions() P0 : value type: Microsoft.UI.Xaml.Controls.ColumnDefinitionCollection After digging in the metadata we can resolve some IIDs of $pColDefs, but at best _WinRT_DisplayInterfaces() only gives us: Class: Microsoft.UI.Xaml.Controls.ColumnDefinitionCollection {CDFBA81A-54FA-557D-A712-21640F16C534} {749BC47C-1743-5C21-9CED-C8A1134C7BA7} {80741C8F-A401-5C63-B6C4-15D165E541C7} {E7BEAEE7-160E-50F7-8789-D63463F979FA} - IDependencyObject {EB24C20B-9816-4AC7-8CFF-36F67A118F4E} {00000038-0000-0000-C000-000000000046} - IWeakReferenceSource {DF0B3D60-548F-101B-8E65-08002B2BD119} - ISupportErrorInfo {00000000-0000-0000-C000-000000000046} - IUnknown {AF86E2E0-B12D-4C6A-9C5A-D7AA65101E90} - IInspectable But what we're looking for is these collection interfaces. TypeDef : Microsoft.UI.Xaml.Controls.ColumnDefinitionCollection Extends : System.Object Interface : Windows.Foundation.Collections.IVector`1<Microsoft.UI.Xaml.Controls.ColumnDefinition> Interface : Windows.Foundation.Collections.IIterable`1<Microsoft.UI.Xaml.Controls.ColumnDefinition> The class explorer tells us IVector should be there. Windows.Foundation.Collections.IVector`1 has a GUID defined as "{913337E9-11A1-4345-A3A2-4E7F956E222D}". so what gives? It does not appear in our list because the IVector`1 GUID is NOT an IID, it is something else called a PIID. It needs to be combined with the datatype in order to give us the IID for Windows.Foundation.Collections.IVector`1<Microsoft.UI.Xaml.Controls.ColumnDefinition>. We can probably just assume the top GUID maps to this... but we really need a way to resolve it properly. The IIDs for paramatiesed interfaces are calculated at runtime so we can't just dig in the metadata for them. Enter RoGetParameterizedTypeInstanceIID. This is the can of worms that I'm still trying to nail down - so stay tuned for part 2! Once all that is sorted I'll also need to fix the WinRT Library generator. At the moment methods involving arrays don't generate correctly, which is kinda important when dealing with collections!!!3 points
-
AutoItHelp v3.3.16.1 with external CSS loading
ioa747 and one other reacted to argumentum for a topic
..ok. Back at it I don't like the current CSS as is in the help site. So, I made a "SciTE4AutoIt3 to CSS" script that outputs a nicer "color list" ( to give it a name, not an HTML guy ) #NoTrayIcon #include <StringConstants.au3> #include <SendMessage.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> Global $g_SciTE_hDirector = 0, $g_idMemo = 0, $g_hGUI = 0 If Not StringInStr($CmdLineRaw, "/ErrorStdOut") Or @Compiled Then Exit MsgBox($MB_TOPMOST, @ScriptName, "Run as script from SciTE4AutoIt3", 60) EndIf Exit main() Func main() Local $iW = 700, $iH = 350, $iErr, $sError = "" $g_hGUI = GUICreate(StringTrimRight(@ScriptName, 4), $iW, $iH) $g_idMemo = GUICtrlCreateEdit("", 2, 2, $iW - 4, $iH - 4, $WS_VSCROLL) GUICtrlSetFont($g_idMemo, 9, 400, 0, "Courier New") GUISetState(@SW_SHOW) Local $sFilename = _SciTE_ExportScriptToHTML(@ScriptFullPath, @TempDir & "\" & @ScriptName & ".htm") $iErr = @error Switch $iErr Case 1 $sError = 'File not created' Case 2 $sError = 'File did not rename back to original' Case 3 $sError = 'AutoIt Script Editor (SciTE4AutoIt3) is not loaded' EndSwitch Local $sData = FileRead($sFilename) FileDelete($sFilename) Local $sChunk = "", $aChunks = StringSplit($sData, "><") For $n = 1 To UBound($aChunks) - 1 If StringInStr($aChunks[$n], @CRLF & ".S") Then $sChunk = $aChunks[$n] ; this is where the CSS is at ExitLoop EndIf Next $aChunks = StringSplit($sChunk, "}{") Local $aCSS[UBound($aChunks) + 2][3] $aCSS[0][0] = 0 For $n = 2 To UBound($aChunks) - 1 Step 2 ; turn the CSS into an array $aChunks[$n] = StringStripWS(StringReplace($aChunks[$n], @CRLF, " "), 7) If $aChunks[$n] = "" Then ContinueLoop $aCSS[0][0] += 1 $aCSS[$aCSS[0][0]][0] = StringStripWS($aChunks[$n - 1], 8) $aCSS[$aCSS[0][0]][1] = $aChunks[$n] $aCSS[$aCSS[0][0]][2] = _SciTE_Colors_Description($aCSS[$aCSS[0][0]][0]) Next ReDim $aCSS[$aCSS[0][0] + 1][3] ; this builds the CSS values for the script examples in the CHM/HTM file Local $sCSS = '/*** SciTE colors ***/' & @CRLF For $n = 1 To $aCSS[0][0] Switch $aCSS[$n][0] Case "span" $sCSS &= '/* ' & $aCSS[$n][0] & " { " & $aCSS[$n][1] & " } " & $aCSS[$n][2] & " */" & @CRLF Case Else $sCSS &= $aCSS[$n][0] & " { " & _SciTE_Colors_RemoveFontSize($aCSS[$n][1]) & " } /* " & $aCSS[$n][2] & " */" & @CRLF EndSwitch Next $sCSS &= '/*** SciTE colors ***/' & @CRLF ;~ ConsoleWrite($sCSS) MemoWrite($sError = "" ? $sCSS : $sError) ; Loop until the user exits. While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop EndSwitch WEnd GUIDelete() Return SetError($iErr, 0, $iErr) EndFunc ;==>main ; Write message to memo Func MemoWrite($sMessage = "", $iAppend = 1) GUICtrlSetData($g_idMemo, $sMessage & @CRLF, $iAppend) EndFunc ;==>MemoWrite Func _SciTE_Colors_RemoveFontSize($sStr) Local $n, $sReturn = "", $aArray = StringSplit($sStr, ";") For $n = 1 To UBound($aArray) - 1 If StringStripWS($aArray[$n], 8) = "" Then ContinueLoop If StringInStr($aArray[$n], "font-size") Then ContinueLoop $sReturn &= $aArray[$n] & ";" Next Return $sReturn EndFunc ;==>_SciTE_Colors_RemoveFontSize Func _SciTE_Colors_Description($sS0) Switch $sS0 ; /*** SciTE colors ***/ /** __SciTE4AutoIt3_Dark.SciTEConfig **/ Case ".S0" Return "White space" Case ".S1" Return "Comment line" Case ".S2" Return "Comment block" Case ".S3" Return "Number" Case ".S4" Return "Function" Case ".S5" Return "Keyword" Case ".S6" Return "Macro" Case ".S7" Return "String" Case ".S8" Return "Operator" Case ".S9" Return "Variable" Case ".S10" Return "Send keys in string" Case ".S11" Return "Pre-Processor" Case ".S12" Return "Special" Case ".S13" Return "Abbrev-Expand" Case ".S14" Return "COM Objects" Case ".S15" Return "Standard UDF's" EndSwitch Return "" EndFunc ;==>_SciTE_Colors_Description ; #FUNCTION# ==================================================================================================================== ; @error: ; 1 = File not created ; 2 = File did not rename back to original ; 3 = SciTE is not loaded ; ; Example: ;~ MsgBox(0, @ScriptName, "File: " & _SciTE_ExportScriptToHTML(@ScriptFullPath, @ScriptFullPath & ".htm") & _ ;~ @LF & @LF & 'Error: ' & @error & @LF & 'Extended: ' & @extended) ; =============================================================================================================================== Func _SciTE_ExportScriptToHTML($sSource, $sDestination) Local $iErr = 1, $iExt = 0, $sDestinationTemp = $sDestination & "~" & TimerInit() & ".htm" If Not _SciTE_GetDirector(True) Then Return SetError(3, 0, "") __SciTE_Send_Command(0, _SciTE_GetDirector(False), 'exportashtml:' & StringReplace($sDestinationTemp, '\', '\\')) If FileGetSize($sDestinationTemp) Then $iExt = Int(Not FileMove($sDestinationTemp, $sDestination, 9)) $iErr = ($iExt ? 2 : 0) EndIf Return SetError($iErr, $iExt, ($iErr ? $sDestinationTemp : $sDestination)) EndFunc ;==>_SciTE_ExportScriptToHTML Func _SciTE_GetDirector($bIsReset = False) Local Enum $SCITE_DIRECTOR = 1 If $bIsReset Or Not IsHWnd($g_SciTE_hDirector) Then $g_SciTE_hDirector = WinGetHandle('DirectorExtension') If @error Then $g_SciTE_hDirector = 0 EndIf Return $g_SciTE_hDirector EndFunc ;==>_SciTE_GetDirector Func __SciTE_Send_Command($hWnd, $hSciTE, $sMsg) Local $bReturn = False, $_WM_COPYDATA = 74, $tagCOPYDATASTRUCT = "ulong_ptr dwData;dword cbData;ptr lpData" If Not (StringStripWS($sMsg, $STR_STRIPALL) == '') Then $sMsg = ':' & Dec(StringTrimLeft($hWnd, StringLen('0x'))) & ':' & $sMsg Local Const $tBuffer = DllStructCreate('char cdata[' & StringLen($sMsg) + 1 & ']') DllStructSetData($tBuffer, 'cdata', $sMsg) Local Const $tCOPYDATASTRUCT = DllStructCreate($tagCOPYDATASTRUCT) DllStructSetData($tCOPYDATASTRUCT, 'dwData', 0) DllStructSetData($tCOPYDATASTRUCT, 'cbData', DllStructGetSize($tBuffer)) DllStructSetData($tCOPYDATASTRUCT, 'lpData', DllStructGetPtr($tBuffer)) _SendMessage($hSciTE, _ $_WM_COPYDATA, _ $hWnd, _ DllStructGetPtr($tCOPYDATASTRUCT)) $bReturn = Not @error EndIf Return $bReturn EndFunc ;==>__SciTE_Send_Command #cs Added for color export. #ce #pragma compile(LegalCopyright, © You) ; Added for color export. Func ForColorExports() Return "This is not meant to run. Added for color export." ; "cmd " ..typing that would expand to "RunWait('"' & @ComSpec & '" /c |', '', @SW_HIDE)" ; The .S13 ("Abbrev-Expand") will not be rendered in the code, thereby preventing the value from being exported. ; for more help go to https://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3/SciTE4AutoIt3-AbbreviationHowTo.html Local $oShell = ObjCreate("shell.application") ; Get the Windows Shell Object Local $oShellWindows = $oShell.Windows() ; Get the collection of open shell Windows Send("{SPACE}") EndFunc ;==>ForColorExports /*** SciTE colors ***/ .S0 { color: #80C0FF; } /* White space */ .S1 { font-style: italic; color: #60A060; } /* Comment line */ .S2 { font-style: italic; color: #60A060; } /* Comment block */ .S3 { color: #C0FFFF; } /* Number */ .S4 { color: #8080FF; } /* Function */ .S5 { color: #C080C0; } /* Keyword */ .S6 { color: #A0A000; } /* Macro */ .S7 { color: #F0E090; } /* String */ .S8 { color: #FF8000; } /* Operator */ .S9 { color: #D0D0D0; } /* Variable */ .S10 { color: #A0A0A0; } /* Send keys in string */ .S11 { color: #8996A8; } /* Pre-Processor */ .S12 { color: #FFAAB7; } /* Special */ .S14 { color: #993399; } /* COM Objects */ .S15 { color: #0080FF; } /* Standard UDF's */ /* span { font-family: 'Courier New'; color: #D0D0D0; font-size: 10pt; } */ /*** SciTE colors ***/ that is easier to see and edit, and with some help for what applies to what. ( you could test online too ) I'll have my test site updated soon(done) to reflect what's in the works. Given that the test site, is testing stuff, some times the prior CSS or JS may be used instead of the current. To clear the cache data, open "inspect data", go to network and tick "Disable cache". Reload the page and that should be all that's needed.2 points -
Controller-Worker-Task Manager Framework
WildByDesign and one other reacted to Trong for a topic
v2: Added AutoStart functionality ; =============================================================================================================================== ; SCRIPT: Controller-Worker-Task Manager Framework ; AUTHOR: Dao Van Trong - TRONG.PRO ; VERSION: 2.0 (Added AutoStart functionality) ; DESCRIPTION: This script implements a robust Controller-Worker-Task architecture for running background processes. ; It is designed to be a flexible framework for automation tasks. ; ; ARCHITECTURE: ; - Controller: The main process that runs persistently. It has no GUI and is controlled entirely via a system tray icon. ; Its responsibilities include: ; 1. Reading the configuration from 'Configs.ini'. ; 2. Creating and managing the tray menu. ; 3. Starting, stopping, and monitoring Worker processes. ; 4. Launching one-shot Task processes. ; 5. Automatically reloading the configuration when 'Configs.ini' is modified. ; 6. Auto-starting specified Workers and Tasks on launch. ; ; - Workers: Long-running background processes that perform recurring tasks (e.g., monitoring, syncing). ; They are started and stopped by the Controller and run completely hidden. ; Each worker monitors the Controller and will self-terminate if the Controller exits. ; ; - Tasks: Short-lived background processes that perform a single, one-shot action (e.g., generate a report). ; They can be configured to run exclusively (locking all other tasks) or concurrently. ; They can also be configured to run as a separate sub-process or directly within the Controller's process. ; ; HOW IT WORKS: ; - IPC (Inter-Process Communication): Communication between the Controller and Workers is handled via the Windows Registry. ; The Controller writes a signal to a specific registry key to gracefully shut down a Worker. ; - Asynchronous Operations: All monitoring (process status, config file changes) and Worker functions are handled ; asynchronously using AdlibRegister, ensuring the Controller remains responsive. ; - Configuration: All Workers and Tasks are defined in the master arrays within this script, but they are enabled, ; disabled, and configured via an external 'Configs.ini' file. This allows for easy customization without ; modifying the source code. ; - Logging: The script generates a detailed log file ('manager.log') in the same directory, recording all major ; events like startup, shutdown, worker status changes, and errors. ; ; PERFORMANCE IMPROVEMENTS: ; - Optimized tray menu handling with reduced event processing overhead ; - Faster exit processing with immediate cleanup ; - Reduced Adlib function frequency for better responsiveness ; - Improved memory management and array operations ; ; NEW FEATURES: ; - On/Off declaration for MasterWorkers and MasterTasks ; - Au3Stripper compatibility with proper function protection ; - Enhanced configuration system ; - AutoStart option for Workers and Tasks ; =============================================================================================================================== #include <TrayConstants.au3> #include <Array.au3> #include <File.au3> #include <FileConstants.au3> ; Au3Stripper protection directives #Au3Stripper_Ignore_Funcs=Worker1Function,Worker2Function,Worker3Function,Worker4Function,Worker5Function,Worker6Function,Worker7Function,Worker8Function,Worker9Function,Worker10Function #Au3Stripper_Ignore_Funcs=TaskA_Function,TaskB_Function,TaskC_Function,TaskD_Function,TaskE_Function,TaskF_Function,TaskG_Function,TaskH_Function,TaskI_Function,TaskJ_Function #Au3Stripper_Ignore_Funcs=_CheckStatus_Adlib,_CheckForConfigChanges_Adlib,_WorkerHeartbeat_Adlib #Au3Stripper_Ignore_Variables=$g_aMasterWorkers,$g_aMasterTasks,$g_aWorkers,$g_aTasks,$g_aWorkerTrayItems,$g_aTaskTrayItems ; =============================================================================================================================== ; --- GLOBAL CONSTANTS AND VARIABLES ; =============================================================================================================================== ; --- Settings --- Global Const $g_sConfigFile = @ScriptDir & "\Configs.ini" Global Const $g_sLogFile = @ScriptDir & "\Manager.log" Global $g_sAppName = "Controller-Worker-Task Manager" Global $g_iCheckConfigInterval = 15000 ; Increased for better performance Global $g_sLastConfigModDate = "" ; --- Registry & IPC --- Global Const $g_sRegBase = "HKCU\Software\ControllerWorkerApp" Global Const $g_iAdlibCheckInterval = 2000 ; Reduced frequency for better performance Global Const $g_iGracefulShutdownTimeout = 2000 ; Reduced for faster exit ; --- Status Constants for internal logic --- Global Const $STATUS_STOPPED = 0, $STATUS_RUNNING = 1, $STATUS_ERROR = 2 ; --- Task Execution Mode & Type Constants --- Global Const $TASK_MODE_EXCLUSIVE = 0, $TASK_MODE_CONCURRENT = 1 Global Const $TASK_RUN_TYPE_SUBAPP = 0, $TASK_RUN_TYPE_DIRECT = 1 ; --- Menu Type Constants --- Global Const $MENU_TYPE_MAIN = 0, $MENU_TYPE_SUB = 1 ; --- Performance optimization flags --- Global $g_bShuttingDown = False Global $g_bConfigReloading = False ; --- MASTER DATA STRUCTURES (Hard-coded definitions) --- ; [InternalName, DisplayName, FunctionName, MenuType, Status(On/Off), AutoStart(On/Off)] Global Const $g_aMasterWorkers[10][6] = [ _ ["CheckResources", "Check Resources", "Worker1Function", $MENU_TYPE_MAIN, "On", "On"], _ ; AutoStart Enabled ["SyncFiles", "Sync Files", "Worker2Function", $MENU_TYPE_MAIN, "On", "Off"], _ ["MonitorNetwork", "Monitor Network", "Worker3Function", $MENU_TYPE_MAIN, "On", "On"], _ ; AutoStart Enabled ["BackupDB", "Backup DB", "Worker4Function", $MENU_TYPE_SUB, "On", "Off"], _ ["CleanupLogs", "Cleanup Logs", "Worker5Function", $MENU_TYPE_SUB, "On", "Off"], _ ["ProcessEmails", "Process Emails", "Worker6Function", $MENU_TYPE_SUB, "On", "Off"], _ ["AutoScreenshot", "Auto Screenshot", "Worker7Function", $MENU_TYPE_SUB, "Off", "Off"], _ ["MonitorTemp", "Monitor Temp", "Worker8Function", $MENU_TYPE_SUB, "Off", "Off"], _ ["CheckUpdates", "Check Updates", "Worker9Function", $MENU_TYPE_SUB, "On", "Off"], _ ["SecurityScan", "Security Scan", "Worker10Function", $MENU_TYPE_SUB, "Off", "Off"] _ ] ; [InternalName, DisplayName, FunctionName, MenuType, ExecutionMode, RunType, Status(On/Off), AutoStart(On/Off)] Global Const $g_aMasterTasks[10][8] = [ _ ["QuickCleanup", "Quick Cleanup", "TaskA_Function", $MENU_TYPE_MAIN, $TASK_MODE_EXCLUSIVE, $TASK_RUN_TYPE_SUBAPP, "On", "Off"], _ ["GenerateReport", "Generate Report", "TaskB_Function", $MENU_TYPE_MAIN, $TASK_MODE_EXCLUSIVE, $TASK_RUN_TYPE_SUBAPP, "On", "On"], _ ; AutoStart Enabled ["SendNotification", "Send Notification (Direct)", "TaskJ_Function", $MENU_TYPE_MAIN, $TASK_MODE_EXCLUSIVE, $TASK_RUN_TYPE_DIRECT, "On", "Off"], _ ["TaskC", "Run Task C (Direct)", "TaskC_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_DIRECT, "On", "Off"], _ ["TaskD", "Run Task D", "TaskD_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP, "Off", "Off"], _ ["TaskE", "Run Task E", "TaskE_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP, "Off", "Off"], _ ["TaskF", "Run Task F", "TaskF_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP, "On", "Off"], _ ["TaskG", "Run Task G", "TaskG_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP, "Off", "Off"], _ ["TaskH", "Run Task H", "TaskH_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP, "On", "Off"], _ ["TaskI", "Run Task I", "TaskI_Function", $MENU_TYPE_SUB, $TASK_MODE_CONCURRENT, $TASK_RUN_TYPE_SUBAPP, "Off", "Off"] _ ] ; --- Dynamic Data Structures (Populated from Master based on INI) --- Global $g_aWorkers, $g_iNumWorkers Global $g_aTasks, $g_iNumTasks ; --- Tray Menu Control Variables --- Global $g_aWorkerTrayItems[1], $g_aTaskTrayItems[1], $g_iTrayExit ; --- Shared Global Variables for Worker processes --- Global $g_sWorkerInternalName, $g_iControllerPID, $g_sWorkerRegKey ; --- Performance optimization variables --- Global $g_iLastStatusCheck = 0 Global $g_iLastConfigCheck = 0 ; =============================================================================================================================== ; --- MAIN SCRIPT LOGIC ; =============================================================================================================================== _Main() ;/** ; * @brief Main entry point of the script. ; * ; * Determines whether to run as the Controller or as a sub-process (Worker/Task) ; * based on the command-line arguments. ; */ Func _Main() If $CmdLine[0] > 0 Then Local $aCmd = StringSplit($CmdLine[1], ":") If $aCmd[0] < 2 Then Exit Local $sType = $aCmd[1], $sInternalName = $aCmd[2], $iControllerPID = ($CmdLine[0] > 1 ? $CmdLine[2] : 0) Switch $sType Case "worker" _RunAsWorker($sInternalName, $iControllerPID) Case "task" _RunAsTask($sInternalName) EndSwitch Else _RunAsController() EndIf EndFunc ;==>_Main ; =============================================================================================================================== ; --- CONTROLLER FUNCTIONS ; =============================================================================================================================== ;/** ; * @brief Initializes the Controller process. ; * ; * This function sets up the entire Controller environment: ; * 1. Cleans up any leftover registry keys from previous runs. ; * 2. Loads the configuration from Configs.ini. ; * 3. Creates the tray menu. ; * 4. Auto-starts any configured items. ; * 5. Registers Adlib functions for background monitoring. ; * 6. Starts the main event loop. ; */ Func _RunAsController() ; Performance optimization: Batch initialization _CleanupAllRegistryKeys() _LoadConfiguration() _CreateTrayMenu() ; Auto-start configured items _AutoStartItems() ; Optimized Adlib registration with performance flags $g_iLastStatusCheck = TimerInit() $g_iLastConfigCheck = TimerInit() AdlibRegister("_CheckStatus_Adlib", $g_iAdlibCheckInterval) AdlibRegister("_CheckForConfigChanges_Adlib", $g_iCheckConfigInterval) _WriteLog("INFO: Controller started successfully.") _ControllerMainLoop() EndFunc ;==>_RunAsController ;/** ; * @brief Loads and parses the configuration from Configs.ini. ; * ; * Enhanced version with On/Off status checking for master arrays. ; * If Configs.ini exists, it reads the settings and the disable lists. ; * If not, it uses the default configuration (all master items with "On" status enabled). ; * It then populates the dynamic $g_aWorkers and $g_aTasks arrays with only the enabled items. ; */ Func _LoadConfiguration() $g_bConfigReloading = True Local $sDisabledWorkers = "", $sDisabledTasks = "" If FileExists($g_sConfigFile) Then $g_sLastConfigModDate = FileGetTime($g_sConfigFile, $FT_MODIFIED, $FT_STRING) $g_sAppName = IniRead($g_sConfigFile, "Settings", "AppName", "Controller Framework") $g_iCheckConfigInterval = IniRead($g_sConfigFile, "Settings", "CheckConfigInterval", 15000) $sDisabledWorkers = "," & IniRead($g_sConfigFile, "Workers", "Disable", "") & "," $sDisabledTasks = "," & IniRead($g_sConfigFile, "Tasks", "Disable", "") & "," Else $g_sLastConfigModDate = "" $sDisabledWorkers = "," $sDisabledTasks = "," EndIf ; Enhanced filtering: Check both INI disable list and master array On/Off status Local $iWorkerCount = 0, $iTaskCount = 0 For $i = 0 To UBound($g_aMasterWorkers) - 1 If $g_aMasterWorkers[$i][4] = "On" And Not StringInStr($sDisabledWorkers, "," & $g_aMasterWorkers[$i][0] & ",") Then $iWorkerCount += 1 EndIf Next For $i = 0 To UBound($g_aMasterTasks) - 1 If $g_aMasterTasks[$i][6] = "On" And Not StringInStr($sDisabledTasks, "," & $g_aMasterTasks[$i][0] & ",") Then $iTaskCount += 1 EndIf Next $g_iNumWorkers = $iWorkerCount $g_iNumTasks = $iTaskCount ; Performance optimization: Only create arrays if needed If $g_iNumWorkers > 0 Then Dim $g_aWorkers[$g_iNumWorkers][8] ; UPDATED: Increased size for AutoStart flag Local $iWorkerIdx = 0 For $i = 0 To UBound($g_aMasterWorkers) - 1 Local $sInternalName = $g_aMasterWorkers[$i][0] If $g_aMasterWorkers[$i][4] = "Off" Or StringInStr($sDisabledWorkers, "," & $sInternalName & ",") Then ContinueLoop $g_aWorkers[$iWorkerIdx][0] = $sInternalName $g_aWorkers[$iWorkerIdx][1] = $g_aMasterWorkers[$i][1] $g_aWorkers[$iWorkerIdx][2] = $g_aMasterWorkers[$i][2] $g_aWorkers[$iWorkerIdx][3] = 0 $g_aWorkers[$iWorkerIdx][4] = False $g_aWorkers[$iWorkerIdx][5] = $STATUS_STOPPED $g_aWorkers[$iWorkerIdx][6] = $g_aMasterWorkers[$i][3] $g_aWorkers[$iWorkerIdx][7] = $g_aMasterWorkers[$i][5] ; NEW: Copy AutoStart flag $iWorkerIdx += 1 Next Else Dim $g_aWorkers[0][0] ; Empty array EndIf If $g_iNumTasks > 0 Then Dim $g_aTasks[$g_iNumTasks][8] ; UPDATED: Increased size for AutoStart flag Local $iTaskIdx = 0 For $i = 0 To UBound($g_aMasterTasks) - 1 Local $sInternalName = $g_aMasterTasks[$i][0] If $g_aMasterTasks[$i][6] = "Off" Or StringInStr($sDisabledTasks, "," & $sInternalName & ",") Then ContinueLoop $g_aTasks[$iTaskIdx][0] = $sInternalName $g_aTasks[$iTaskIdx][1] = $g_aMasterTasks[$i][1] $g_aTasks[$iTaskIdx][2] = $g_aMasterTasks[$i][2] $g_aTasks[$iTaskIdx][3] = 0 $g_aTasks[$iTaskIdx][4] = $g_aMasterTasks[$i][4] $g_aTasks[$iTaskIdx][5] = $g_aMasterTasks[$i][5] $g_aTasks[$iTaskIdx][6] = $g_aMasterTasks[$i][3] $g_aTasks[$iTaskIdx][7] = $g_aMasterTasks[$i][7] ; NEW: Copy AutoStart flag $iTaskIdx += 1 Next Else Dim $g_aTasks[0][0] ; Empty array EndIf $g_bConfigReloading = False EndFunc ;==>_LoadConfiguration ;/** ; * @brief Creates the entire tray menu structure based on the loaded configuration. ; * ; * Enhanced version with better performance and empty array handling. ; */ Func _CreateTrayMenu() Opt("TrayMenuMode", 3) TraySetToolTip($g_sAppName) ; Performance optimization: Only create arrays if needed If $g_iNumWorkers > 0 Then ReDim $g_aWorkerTrayItems[$g_iNumWorkers] Local $hSubWorkersMenu = 0 For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][6] = $MENU_TYPE_MAIN Then $g_aWorkerTrayItems[$i] = TrayCreateItem("[OFF] " & $g_aWorkers[$i][1]) Else If $hSubWorkersMenu = 0 Then $hSubWorkersMenu = TrayCreateMenu("Sub Workers") $g_aWorkerTrayItems[$i] = TrayCreateItem("[OFF] " & $g_aWorkers[$i][1], $hSubWorkersMenu) EndIf Next Else ReDim $g_aWorkerTrayItems[0] EndIf TrayCreateItem("") If $g_iNumTasks > 0 Then ReDim $g_aTaskTrayItems[$g_iNumTasks] Local $hSubTasksMenu = 0 For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][6] = $MENU_TYPE_MAIN Then $g_aTaskTrayItems[$i] = TrayCreateItem($g_aTasks[$i][1]) Else If $hSubTasksMenu = 0 Then $hSubTasksMenu = TrayCreateMenu("Sub Tasks") $g_aTaskTrayItems[$i] = TrayCreateItem($g_aTasks[$i][1], $hSubTasksMenu) EndIf Next Else ReDim $g_aTaskTrayItems[0] EndIf TrayCreateItem("") $g_iTrayExit = TrayCreateItem("Exit") TraySetState(1) EndFunc ;==>_CreateTrayMenu ;/** ; * @brief The main event loop for the Controller. ; * ; * Enhanced with performance optimizations and faster exit handling. ; */ Func _ControllerMainLoop() While Not $g_bShuttingDown Local $iTrayMsg = TrayGetMsg() Switch $iTrayMsg Case 0 ; No message - continue Case $g_iTrayExit ; Immediate exit handling for better responsiveness $g_bShuttingDown = True _ExitController() Case Else ; Performance optimization: Early exit if reloading config If $g_bConfigReloading Then ContinueLoop Local $iIndex = _GetIndexFromTrayID($iTrayMsg, $g_aWorkerTrayItems) If $iIndex <> -1 Then _HandleWorkerClick($iIndex) ContinueLoop EndIf $iIndex = _GetIndexFromTrayID($iTrayMsg, $g_aTaskTrayItems) If $iIndex <> -1 Then _HandleTaskClick($iIndex) ContinueLoop EndIf EndSwitch Sleep(50) ; Reduced sleep for better responsiveness WEnd EndFunc ;==>_ControllerMainLoop ;/** ; * @brief Handles a click on a Worker menu item. ; * @param $iIndex The index of the clicked worker in the $g_aWorkers array. ; */ Func _HandleWorkerClick($iIndex) If $g_bShuttingDown Or $g_bConfigReloading Then Return _UpdateWorkerState($iIndex, Not $g_aWorkers[$iIndex][4]) EndFunc ;==>_HandleWorkerClick ;/** ; * @brief Handles a click on a Task menu item. ; * @param $iIndex The index of the clicked task in the $g_aTasks array. ; */ Func _HandleTaskClick($iIndex) If $g_bShuttingDown Or $g_bConfigReloading Then Return _RunTask($iIndex) EndFunc ;==>_HandleTaskClick ;/** ; * @brief Central function to change a worker's state (on/off). ; * @param $iIndex The index of the worker. ; * @param $bNewState The new state to apply (True for ON, False for OFF). ; */ Func _UpdateWorkerState($iIndex, $bNewState) If $g_iNumWorkers = 0 Or $iIndex < 0 Or $iIndex >= $g_iNumWorkers Then Return $g_aWorkers[$iIndex][4] = $bNewState If $bNewState Then _StartWorker($iIndex) Else _StopWorker($iIndex) EndIf _UpdateTrayItemForWorker($iIndex) EndFunc ;==>_UpdateWorkerState ;/** ; * @brief Updates a worker's tray menu item text and checked state. ; * @param $iIndex The index of the worker. ; */ Func _UpdateTrayItemForWorker($iIndex) If $g_iNumWorkers = 0 Or $iIndex < 0 Or $iIndex >= $g_iNumWorkers Then Return Local $sPrefix, $iTrayState If $g_aWorkers[$iIndex][4] Then $sPrefix = "[ON] " $iTrayState = $TRAY_CHECKED Else $sPrefix = "[OFF] " $iTrayState = $TRAY_UNCHECKED EndIf TrayItemSetText($g_aWorkerTrayItems[$iIndex], $sPrefix & $g_aWorkers[$iIndex][1]) TrayItemSetState($g_aWorkerTrayItems[$iIndex], $iTrayState) EndFunc ;==>_UpdateTrayItemForWorker ;/** ; * @brief Starts a worker sub-process. ; * @param $iIndex The index of the worker. ; */ Func _StartWorker($iIndex) If $g_iNumWorkers = 0 Or $iIndex < 0 Or $iIndex >= $g_iNumWorkers Then Return If ProcessExists($g_aWorkers[$iIndex][3]) Then Return Local $sCommand = 'worker:' & $g_aWorkers[$iIndex][0] _WriteLog("INFO: Starting Worker '" & $g_aWorkers[$iIndex][1] & "'...") Local $iPID = _RunScript($sCommand) If $iPID > 0 Then $g_aWorkers[$iIndex][3] = $iPID $g_aWorkers[$iIndex][5] = $STATUS_RUNNING Else _WriteLog("ERROR: Failed to start Worker '" & $g_aWorkers[$iIndex][1] & "'.") $g_aWorkers[$iIndex][4] = False $g_aWorkers[$iIndex][5] = $STATUS_ERROR EndIf EndFunc ;==>_StartWorker ;/** ; * @brief Stops a worker sub-process gracefully. ; * @param $iIndex The index of the worker. ; */ Func _StopWorker($iIndex) If $g_iNumWorkers = 0 Or $iIndex < 0 Or $iIndex >= $g_iNumWorkers Then Return Local $iPID = $g_aWorkers[$iIndex][3] If $iPID = 0 Or Not ProcessExists($iPID) Then $g_aWorkers[$iIndex][3] = 0 $g_aWorkers[$iIndex][5] = $STATUS_STOPPED Return EndIf _WriteLog("INFO: Stopping Worker '" & $g_aWorkers[$iIndex][1] & "' (PID: " & $iPID & ")...") Local $sRegKey = $g_sRegBase & "\" & $g_aWorkers[$iIndex][0] RegWrite($sRegKey, "Signal", "REG_SZ", "exit") If @error Then _WriteLog("ERROR: Failed to write exit signal to registry for " & $g_aWorkers[$iIndex][0]) Local $iResult = ProcessWaitClose($iPID, $g_iGracefulShutdownTimeout / 1000) If $iResult = 0 Then _WriteLog("WARN: Worker PID " & $iPID & " did not respond. Forcing shutdown.") ProcessClose($iPID) EndIf RegDelete($sRegKey) $g_aWorkers[$iIndex][3] = 0 $g_aWorkers[$iIndex][5] = $STATUS_STOPPED EndFunc ;==>_StopWorker ;/** ; * @brief Runs a task either directly or as a sub-process. ; * @param $iIndex The index of the task. ; */ Func _RunTask($iIndex) If $g_iNumTasks = 0 Or $iIndex < 0 Or $iIndex >= $g_iNumTasks Then Return Local $sTaskName = $g_aTasks[$iIndex][1] _WriteLog("INFO: Running Task '" & $sTaskName & "'...") If $g_aTasks[$iIndex][5] = $TASK_RUN_TYPE_DIRECT Then TrayItemSetState($g_aTaskTrayItems[$iIndex], $TRAY_DISABLE) Call($g_aTasks[$iIndex][2], $sTaskName) TrayItemSetState($g_aTaskTrayItems[$iIndex], $TRAY_ENABLE) _WriteLog("INFO: Direct Task '" & $sTaskName & "' has completed.") Else If $g_aTasks[$iIndex][3] <> 0 And ProcessExists($g_aTasks[$iIndex][3]) Then Return Local $sCommand = 'task:' & $g_aTasks[$iIndex][0] Local $iPID = _RunScript($sCommand, False) If $iPID > 0 Then $g_aTasks[$iIndex][3] = $iPID _UpdateAllTaskMenusState() Else _WriteLog("ERROR: Failed to run Task '" & $sTaskName & "'.") EndIf EndIf EndFunc ;==>_RunTask ;/** ; * @brief Automatically starts workers and tasks that are configured to run on startup. ; */ Func _AutoStartItems() _WriteLog("INFO: Checking for items to auto-start...") ; Auto-start workers If $g_iNumWorkers > 0 Then For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][7] = "On" Then _WriteLog("INFO: Auto-starting Worker '" & $g_aWorkers[$i][1] & "'...") _UpdateWorkerState($i, True) EndIf Next EndIf ; Auto-start tasks If $g_iNumTasks > 0 Then For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][7] = "On" Then _WriteLog("INFO: Auto-starting Task '" & $g_aTasks[$i][1] & "'...") _RunTask($i) EndIf Next EndIf EndFunc ;==>_AutoStartItems ;/** ; * @brief Optimized Adlib function to monitor the status of running workers and tasks. ; */ Func _CheckStatus_Adlib() ; Performance optimization: Skip if shutting down or reloading If $g_bShuttingDown Or $g_bConfigReloading Then Return ; Rate limiting for better performance If TimerDiff($g_iLastStatusCheck) < $g_iAdlibCheckInterval Then Return $g_iLastStatusCheck = TimerInit() ; Check workers only if we have any If $g_iNumWorkers > 0 Then For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][4] And Not ProcessExists($g_aWorkers[$i][3]) Then _WriteLog("WARN: Worker '" & $g_aWorkers[$i][1] & "' died. Restarting...") $g_aWorkers[$i][5] = $STATUS_ERROR _UpdateTrayItemForWorker($i) _StartWorker($i) EndIf Next EndIf ; Check tasks only if we have any If $g_iNumTasks > 0 Then Local $bTaskStateChanged = False For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][5] = $TASK_RUN_TYPE_SUBAPP And $g_aTasks[$i][3] > 0 And Not ProcessExists($g_aTasks[$i][3]) Then $g_aTasks[$i][3] = 0 $bTaskStateChanged = True EndIf Next If $bTaskStateChanged Then _UpdateAllTaskMenusState() EndIf EndFunc ;==>_CheckStatus_Adlib ;/** ; * @brief Checks if any exclusive task is currently running as a sub-process. ; * @return True if an exclusive task is running, otherwise False. ; */ Func _IsExclusiveTaskRunning() If $g_iNumTasks = 0 Then Return False For $i = 0 To $g_iNumTasks - 1 If $g_aTasks[$i][4] = $TASK_MODE_EXCLUSIVE And $g_aTasks[$i][3] > 0 And ProcessExists($g_aTasks[$i][3]) Then Return True EndIf Next Return False EndFunc ;==>_IsExclusiveTaskRunning ;/** ; * @brief Updates the enabled/disabled state of all task menu items based on current activity. ; */ Func _UpdateAllTaskMenusState() If $g_iNumTasks = 0 Then Return Local $bExclusiveRunning = _IsExclusiveTaskRunning() For $i = 0 To $g_iNumTasks - 1 If $bExclusiveRunning Then TrayItemSetState($g_aTaskTrayItems[$i], $TRAY_DISABLE) Else If $g_aTasks[$i][3] > 0 And ProcessExists($g_aTasks[$i][3]) Then TrayItemSetState($g_aTaskTrayItems[$i], $TRAY_DISABLE) Else TrayItemSetState($g_aTaskTrayItems[$i], $TRAY_ENABLE) EndIf EndIf Next EndFunc ;==>_UpdateAllTaskMenusState ;/** ; * @brief Optimized Adlib function to check for modifications to the Configs.ini file. ; */ Func _CheckForConfigChanges_Adlib() ; Performance optimization: Skip if shutting down If $g_bShuttingDown Then Return ; Rate limiting for better performance If TimerDiff($g_iLastConfigCheck) < $g_iCheckConfigInterval Then Return $g_iLastConfigCheck = TimerInit() Local $sCurrentModDate = FileGetTime($g_sConfigFile, $FT_MODIFIED, $FT_STRING) If $sCurrentModDate <> $g_sLastConfigModDate And $sCurrentModDate <> "" Then _WriteLog("INFO: Configuration file change detected. Reloading...") $g_bConfigReloading = True _UnregisterAllMasterAdlibs() _StopAllWorkers() TraySetState(2) _LoadConfiguration() _CreateTrayMenu() ; Re-register Adlib functions after config reload AdlibRegister("_CheckStatus_Adlib", $g_iAdlibCheckInterval) AdlibRegister("_CheckForConfigChanges_Adlib", $g_iCheckConfigInterval) _WriteLog("INFO: Configuration reloaded and menu recreated.") EndIf EndFunc ;==>_CheckForConfigChanges_Adlib ;/** ; * @brief Stops all currently active workers with performance optimization. ; */ Func _StopAllWorkers() If $g_iNumWorkers = 0 Then Return _WriteLog("INFO: Stopping all workers...") ; Performance optimization: Parallel shutdown approach Local $aWorkerPIDs[$g_iNumWorkers] Local $aWorkerRegKeys[$g_iNumWorkers] ; First pass: Send exit signals to all workers For $i = 0 To $g_iNumWorkers - 1 If $g_aWorkers[$i][4] And $g_aWorkers[$i][3] > 0 And ProcessExists($g_aWorkers[$i][3]) Then $aWorkerPIDs[$i] = $g_aWorkers[$i][3] $aWorkerRegKeys[$i] = $g_sRegBase & "\" & $g_aWorkers[$i][0] RegWrite($aWorkerRegKeys[$i], "Signal", "REG_SZ", "exit") If @error Then _WriteLog("ERROR: Failed to write exit signal for " & $g_aWorkers[$i][0]) Else $aWorkerPIDs[$i] = 0 EndIf Next ; Wait for graceful shutdown Sleep(500) ; Second pass: Force close any remaining processes For $i = 0 To $g_iNumWorkers - 1 If $aWorkerPIDs[$i] > 0 Then If ProcessExists($aWorkerPIDs[$i]) Then _WriteLog("WARN: Force closing Worker PID " & $aWorkerPIDs[$i]) ProcessClose($aWorkerPIDs[$i]) EndIf RegDelete($aWorkerRegKeys[$i]) $g_aWorkers[$i][3] = 0 $g_aWorkers[$i][4] = False $g_aWorkers[$i][5] = $STATUS_STOPPED EndIf Next EndFunc ;==>_StopAllWorkers ;/** ; * @brief A generic function to run the script as a sub-process. ; * @param $sArgument The argument to pass to the new process (e.g., "worker:MyWorker"). ; * @param $bPassControllerPID If True, the current controller's PID is passed as the second argument. ; * @return The PID of the new process, or 0 on failure. ; */ Func _RunScript($sArgument, $bPassControllerPID = True) Local $sControllerPID = ($bPassControllerPID ? " " & @AutoItPID : "") Local $sCommand = '"' & @ScriptFullPath & '" "' & $sArgument & '"' & $sControllerPID Local $sExecutable = (@Compiled ? "" : '"' & @AutoItExe & '" ') Return Run($sExecutable & $sCommand, @ScriptDir, @SW_HIDE) EndFunc ;==>_RunScript ;/** ; * @brief Performs all necessary cleanup before the Controller exits. ; * Enhanced with faster shutdown process. ; */ Func _ExitController() $g_bShuttingDown = True _WriteLog("INFO: Controller shutting down...") ; Immediate cleanup for faster exit _UnregisterAllMasterAdlibs() _StopAllWorkers() _CleanupAllRegistryKeys() _WriteLog("INFO: Controller shutdown complete.") Exit EndFunc ;==>_ExitController ;/** ; * @brief Enhanced function to unregister all possible Adlib callbacks. ; * Now includes protection for Au3Stripper and handles empty arrays. ; */ Func _UnregisterAllMasterAdlibs() AdlibUnRegister("_CheckStatus_Adlib") AdlibUnRegister("_CheckForConfigChanges_Adlib") ; Unregister all master worker functions (protected from Au3Stripper) For $i = 0 To UBound($g_aMasterWorkers) - 1 AdlibUnRegister($g_aMasterWorkers[$i][2]) Next EndFunc ;==>_UnregisterAllMasterAdlibs ;/** ; * @brief Deletes the entire registry key used by the application for IPC. ; */ Func _CleanupAllRegistryKeys() RegDelete($g_sRegBase) If @error Then _WriteLog("WARN: Registry key cleanup - base key may not exist: " & $g_sRegBase) EndFunc ;==>_CleanupAllRegistryKeys ;/** ; * @brief Enhanced function to find array index with bounds checking. ; * @param $nID The tray item ID to find. ; * @param $aTrayItems The array of tray item IDs to search in. ; * @return The array index if found, otherwise -1. ; */ Func _GetIndexFromTrayID($nID, ByRef $aTrayItems) Local $iUBound = UBound($aTrayItems) If $iUBound = 0 Then Return -1 For $i = 0 To $iUBound - 1 If $aTrayItems[$i] = $nID Then Return $i Next Return -1 EndFunc ;==>_GetIndexFromTrayID ;/** ; * @brief Enhanced logging function with better performance and error handling. ; * @param $sMessage The message to log. ; */ Func _WriteLog($sMessage) Local $sTimeStamp = @YEAR & "/" & @MON & "/" & @MDAY & " " & @HOUR & ":" & @MIN & ":" & @SEC Local $sFormattedMessage = $sTimeStamp & " - " & $sMessage & @CRLF ConsoleWrite($sFormattedMessage) ; Performance optimization: Non-blocking file write Local $hFile = FileOpen($g_sLogFile, $FO_APPEND + $FO_UTF8_NOBOM) If $hFile <> -1 Then FileWrite($hFile, $sFormattedMessage) FileClose($hFile) EndIf EndFunc ;==>_WriteLog ; =============================================================================================================================== ; --- WORKER / TASK SUB-PROCESS EXECUTION ; =============================================================================================================================== ;/** ; * @brief Initializes the script when run as a Worker sub-process. ; * @param $sInternalName The internal name of the worker to run. ; * @param $iControllerPID The PID of the parent Controller process to monitor. ; */ Func _RunAsWorker($sInternalName, $iControllerPID) $g_sWorkerInternalName = $sInternalName $g_iControllerPID = $iControllerPID $g_sWorkerRegKey = $g_sRegBase & "\" & $sInternalName RegDelete($g_sWorkerRegKey) Local $sFunction = "" For $i = 0 To UBound($g_aMasterWorkers) - 1 If $g_aMasterWorkers[$i][0] = $sInternalName Then $sFunction = $g_aMasterWorkers[$i][2] ExitLoop EndIf Next If $sFunction = "" Then Exit ; Performance optimization: Longer intervals for worker processes AdlibRegister($sFunction, 1000) AdlibRegister("_WorkerHeartbeat_Adlib", 3000) ; Reduced frequency While 1 Sleep(200) ; Slightly longer sleep for worker processes WEnd EndFunc ;==>_RunAsWorker ;/** ; * @brief Enhanced Adlib function for workers to monitor the Controller and exit signals. ; */ Func _WorkerHeartbeat_Adlib() ; Check if controller is still running If $g_iControllerPID > 0 And Not ProcessExists($g_iControllerPID) Then _WorkerExitGracefully() Return EndIf ; Check for exit signal from registry Local $sSignal = RegRead($g_sWorkerRegKey, "Signal") If @error Then _WorkerExitGracefully() Return EndIf If $sSignal = "exit" Then _WorkerExitGracefully() EndIf EndFunc ;==>_WorkerHeartbeat_Adlib ;/** ; * @brief Enhanced cleanup function for Workers before exit. ; */ Func _WorkerExitGracefully() AdlibUnRegister("_WorkerHeartbeat_Adlib") ; Find and unregister the specific worker function Local $sFunction = "" For $i = 0 To UBound($g_aMasterWorkers) - 1 If $g_aMasterWorkers[$i][0] = $g_sWorkerInternalName Then $sFunction = $g_aMasterWorkers[$i][2] ExitLoop EndIf Next If $sFunction <> "" Then AdlibUnRegister($sFunction) RegDelete($g_sWorkerRegKey) Exit EndFunc ;==>_WorkerExitGracefully ;/** ; * @brief Initializes the script when run as a Task sub-process. ; * @param $sInternalName The internal name of the task to run. ; */ Func _RunAsTask($sInternalName) Local $sFunction, $sDisplayName For $i = 0 To UBound($g_aMasterTasks) - 1 If $g_aMasterTasks[$i][0] = $sInternalName Then $sDisplayName = $g_aMasterTasks[$i][1] $sFunction = $g_aMasterTasks[$i][2] ExitLoop EndIf Next If $sFunction = "" Then Exit Call($sFunction, $sDisplayName) Exit EndFunc ;==>_RunAsTask ; =============================================================================================================================== ; --- SPECIFIC WORKER/TASK FUNCTIONS (IMPLEMENTATION) ; --- These functions are protected by Au3Stripper directives ; =============================================================================================================================== Func Worker1Function() _WriteLog("Worker 'Check Resources' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker1Function Func Worker2Function() _WriteLog("Worker 'Sync Files' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker2Function Func Worker3Function() _WriteLog("Worker 'Monitor Network' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker3Function Func Worker4Function() _WriteLog("Worker 'Backup DB' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker4Function Func Worker5Function() _WriteLog("Worker 'Cleanup Logs' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker5Function Func Worker6Function() _WriteLog("Worker 'Process Emails' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker6Function Func Worker7Function() _WriteLog("Worker 'Auto Screenshot' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker7Function Func Worker8Function() _WriteLog("Worker 'Monitor Temp' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker8Function Func Worker9Function() _WriteLog("Worker 'Check Updates' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker9Function Func Worker10Function() _WriteLog("Worker 'Security Scan' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>Worker10Function Func TaskA_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(2000) EndFunc ;==>TaskA_Function Func TaskB_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(3000) EndFunc ;==>TaskB_Function Func TaskC_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here EndFunc ;==>TaskC_Function Func TaskD_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskD_Function Func TaskE_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskE_Function Func TaskF_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskF_Function Func TaskG_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskG_Function Func TaskH_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskH_Function Func TaskI_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskI_Function Func TaskJ_Function($sName) _WriteLog("Task '" & $sName & "' is running...") ; This is PlaceHoder - Your Code Replace Here Sleep(1000) EndFunc ;==>TaskJ_Function Eg: Configs.ini ; ====================================================================== ; Configuration file for the Controller-Worker-Task Manager ; ; Instructions: ; - To enable an option, remove the semicolon (;) from the beginning of the line. ; - Changes made to this file will be automatically detected and ; applied by the program without requiring a restart. ; ====================================================================== [Settings] ; The application name that will be displayed in the system tray tooltip. AppName=My Custom Automation Suite ; The interval (in milliseconds) for checking this configuration file for changes. ; The default value in the script is 15000 (which is 15 seconds). CheckConfigInterval=15000 [Workers] ; List the InternalName of the Workers you want to DISABLE, separated by commas (with no spaces). ; Even if a Worker is set to "On" in the script's master array, listing it here ; will prevent it from being loaded and appearing in the tray menu. ; ; Example: Disable=SyncFiles,CleanupLogs ; ; Available Workers (InternalName from the script): ; CheckResources, SyncFiles, MonitorNetwork, BackupDB, CleanupLogs, ProcessEmails, ; AutoScreenshot, MonitorTemp, CheckUpdates, SecurityScan ; ; This example will disable the "Backup DB" and "Process Emails" workers. Disable=BackupDB,ProcessEmails [Tasks] ; List the InternalName of the Tasks you want to DISABLE, separated by commas. ; Similar to Workers, any Task listed here will be disabled. ; ; Available Tasks (InternalName from the script): ; QuickCleanup, GenerateReport, SendNotification, TaskC, TaskD, TaskE, ; TaskF, TaskG, TaskH, TaskI ; ; This example will disable "Run Task F" and "Run Task H". Disable=TaskF,TaskH2 points -
BETA: SciTE v5x & lua Dynamic_include and "Smart" AutoComplete for Vars/UDFs/Abbrevs
WildByDesign and one other reacted to Jos for a topic
It checks for the environment variables "SCITE_USERHOME" and then "SCITE_HOME" and when they are not defined assumes a portable version is used so will default to the directory the AU3STRIPPER program is located in.2 points -
I hope someone can give me help with understanding this. I am testing manipulating AutoIt arrays via COM objects. I can make AutoIt pass me the underlying variant ptr this way, and as i understand it, AutoIt uses varaints internally for values. When calling the method with a array the call takes longer. Since i can modify the variable directly, i expect it does not clone the value, yet arrays take longer, so it's doing something. Also. The size of the array does seem to affect time taken. Does anyone have any ideas what is causing this behavior? #include <WinAPICom.au3> Func F1($pObject, $pVariant) return 0 EndFunc $tObject = DllStructCreate("ptr VTableAddress;ptr VTableMethods[4];") DllStructSetData($tObject, "VTableAddress", DllStructGetPtr($tObject, "VTableMethods")) Local $hF1 = DllCallbackRegister(F1, "LONG", "PTR;PTR") Local $pF1 = DllCallbackGetPtr($hF1) DllStructSetData($tObject, "VTableMethods", $pF1, 1) Local $pObject = DllStructGetPtr($tObject) $oObject = ObjCreateInterface($pObject, _WinAPI_CreateGUID(), "f1 HRESULT(variant*);", False) ;------------------------------------------------------------------------------------------- $s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra tristique felis at dapibus. Vivamus odio lorem, feugiat ut porttitor ac, vehicula sed diam. Donec facilisis quam vitae quam sollicitudin tempus. Quisque ligula sapien, convallis in enim quis, porttitor bibendum lacus. Aenean sollicitudin sit amet augue hendrerit tristique. Nam non est sollicitudin lorem semper tempus ac id tellus. Ut id urna sed justo maximus condimentum ut sed nibh. Integer sit amet consectetur leo. Ut consectetur, nisl eget placerat dignissim, quam dolor rutrum lectus, nec sollicitudin nunc ipsum quis turpis. Maecenas venenatis vel neque vitae aliquam. Etiam id elit quis arcu blandit luctus id ac mauris. Etiam cursus bibendum ultricies. Morbi vitae pellentesque eros, at ullamcorper neque. Duis luctus semper euismod. Etiam vel dui sit amet ante faucibus lacinia non et ante. Quisque id mauris ultrices, congue dui vitae, semper justo. Quisque a placerat metus, vitae ultrices massa. Nunc iaculis faucibus quam quis tincidunt. Integer suscipit ullamcorper felis, eu porttitor nibh sodales ut. Aenean quis fermentum nisl. Maecenas vestibulum hendrerit dolor ac ornare. Mauris vulputate nulla ut nunc ultricies faucibus. Vestibulum ligula enim, vestibulum vitae mauris in, vehicula aliquet nibh. Nunc viverra erat massa, nec scelerisque lacus posuere quis. Maecenas nec neque facilisis, malesuada urna a, iaculis sem. Donec volutpat eget enim nec tempus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque vitae est elementum, feugiat ligula sit amet, porttitor turpis. Aliquam erat volutpat. Quisque id luctus leo. Vestibulum egestas, nibh id euismod semper, sem tellus dictum metus, nec ullamcorper tellus nisi a sapien. Nunc rutrum, mauris eu lacinia tincidunt, velit augue interdum massa, eu porta odio massa ac ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Curabitur semper sed dolor ut vulputate. Cras cursus odio eu felis tristique, non fermentum tellus bibendum. Mauris laoreet mattis blandit. Morbi eget viverra diam. Nulla a venenatis enim, vitae ullamcorper nisi. Cras feugiat felis id orci sagittis rhoncus. Proin congue tempor urna id viverra. Aliquam scelerisque leo sit amet justo laoreet pulvinar. Integer risus enim, viverra at tortor nec, egestas rutrum massa. Cras id velit imperdiet, elementum ante sit amet, tincidunt nunc. In facilisis mi a suscipit mollis. Donec ornare ante quis sodales vestibulum. Phasellus eget tellus erat. Sed pellentesque eleifend mauris vel malesuada. Quisque orci felis, fringilla vel tellus et, vestibulum efficitur lacus. Nullam dictum ligula non faucibus fermentum. Pellentesque dignissim, velit in scelerisque luctus, lacus arcu fermentum nulla, vel sodales nibh tortor in elit. Curabitur ut orci varius, scelerisque lectus volutpat, posuere turpis. Integer efficitur arcu nec ornare lobortis. Fusce lobortis, odio ut sodales pulvinar, neque nisl eleifend tortor, in dignissim ipsum purus nec nunc. Vivamus auctor lectus volutpat nunc congue sollicitudin nec eu nisl. Cras elementum auctor ligula, et egestas augue pharetra eu. Nam fermentum condimentum finibus. Aliquam a suscipit sem. Cras pretium neque nec ullamcorper aliquet. Sed vitae condimentum est. Curabitur mattis posuere rhoncus. Sed accumsan, quam nec mollis faucibus, velit odio ornare velit, sit amet fermentum enim." $s = $s & $s & $s $aArray = StringSplit($s, "", 2) $iNumber = 0xabc ConsoleWrite("Array:"&@CRLF) $hTime = TimerInit() $oObject.f1($aArray) ConsoleWrite(" variant*: " & TimerDiff($hTime)&@CRLF) ConsoleWrite("Number:"&@CRLF) $hTime = TimerInit() $oObject.f1($iNumber) ConsoleWrite(" variant*: " & TimerDiff($hTime)&@CRLF)1 point
-
@jugador, guess it is you that made the bug report #4045 ... right? What's up with that last comment in that report, or did we miss any promised SLA in our mutual signed contract?1 point
-
WebDriver attach firefox instance
SOLVE-SMART reacted to mLipok for a topic
Working example: #include <MsgBoxConstants.au3> #include "wd_helper.au3" _Example() Func _Example() Run('"C:\Program Files\Mozilla Firefox\firefox.exe" --marionette -profile C:\FirefoxTEMP') _WD_Option('Driver', 'geckodriver.exe') _WD_Option('DriverParams', '--log trace --connect-existing --marionette-port 2828') _WD_Option('Port', 4444) _WD_Startup() Local $sSession = _WD_CreateSession() _WD_Navigate($sSession, "https://www.autoitscript.com/forum") MsgBox($MB_OK + $MB_TOPMOST + $MB_ICONINFORMATION, @ScriptName, "After attaching") _WD_Shutdown() EndFunc ;==>_Example1 point -
WebP v0.5.0 build 2025-08-10 beta
UEZ reacted to pixelsearch for a topic
...so I added it to the menu, all your examples have been added just now (the script in preceding post has been updated)1 point -
_AutoItErrorTrap.au3 (UDF) - Error detection in AutoIt scripts!
argumentum reacted to jimmy123j for a topic
Thanks argumentum my purpose is dismiss that default message and show the custom message with correct script line, error var and specific handle flow like restart or somthing I'll try it, thanks again1 point -
Controller-Worker-Task Manager Framework
WildByDesign reacted to Trong for a topic
That name is wrong. Your document is absolutely correct, it's just something I added when I couldn't remember exactly what it was! It's just a quick edit, just search and replace to use the code quickly!1 point -
WebP v0.5.0 build 2025-08-10 beta
pixelsearch reacted to UEZ for a topic
I added WebP Example05.1.au3. Thanks for your contribution. I'm excited to see the result...1 point -
WebP v0.5.0 build 2025-08-10 beta
UEZ reacted to pixelsearch for a topic
Thanks for the explanation ! For the record, I am scripting the following, to access easily any of your examples : #include <GUIConstantsEx.au3> #include <MsgBoxConstants.au3> Opt("MustDeclareVars", 1) If _Doubleton("AutoIt - UEZ WebP all examples") Then Exit ; script already launched + user wants to quit Example() ;============================================== Func Example() Local $hGUI, $idMenu, $iPID, $nMsg, $sFileName Local $aExample[][3] = [ _ ["01", "WebP Example01.au3", "View WebP image (from file, shrinked at 75%)"], _ ["02", "WebP Example02.au3", "View WebP image (from memory, full size)"], _ ["03", "WebP Example03.au3", "WebP image information"], _ ["04", "WebP Example04.au3", "Convert to WebP lossless && lossy (simple), save"], _ ["05", "WebP Example05.au3", "Convert to WebP lossy (advanced), no save"], _ ["05.1", "WebP Example05.1.au3", "Convert to WebP lossy (advanced), save"], _ ["06", "WebP Example06.au3", "Extract all frames from an animated WebP file"], _ ["07", "WebP Example07.au3", "Play an animated WebP file in GUI (same thread)"], _ ["08.1", "WebP Example08.1.au3", "Create WebP animation from GDI+ image files"], _ ["09", "WebP Example09.au3", "Create WebP animation from screen capture"], _ ["10.1", "WebP Example10.1.au3", "Converts GIF animation to WebP animation"], _ ["11", "WebP Example11.au3", "Display the differences of 2 WebP images (same dimension"], _ ["12", "WebP Example12.au3", "Resize a WebP image"], _ ["13", "WebP Example13.au3", "Estimate the quality of a WebP image"], _ ["14.1", "WebP Example14.1.au3", "Play an animated WebP file on Desktop (separated thread)"], _ ["15", "WebP Example15.au3", "Play an animated WebP file in GUI (separated thread)"], _ ["16.1", "WebP Example16.1.au3", "Converts a PNG animation to a WebP animation"], _ ["17", "WebP Example17.au3", "Re-encode a WebP image"], _ ["18", "WebP Example18.au3", "Re-encode an animated WebP file"] ] $hGUI = GUICreate("UEZ WebP all examples", 400, 200) $idMenu = GUICtrlCreateMenu("Examples") ; create all menu items immediately after this line (+++) For $i = 0 To Ubound($aExample) - 1 GUICtrlCreateMenuItem($aExample[$i][0] & @TAB & $aExample[$i][2], $idMenu, -1, 1) ; last param. 1 = create a menuradioitem Next GUISetState(@SW_SHOW) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE ExitLoop Case $idMenu + 1 To $idMenu + Ubound($aExample) $sFileName = @ScriptDir & "\" & $aExample[$nMsg - ($idMenu + 1)][1] If Not FileExists($sFileName) Then Msgbox($MB_TOPMOST, "Script not found", $sFileName) Else $iPID = Run(@AutoItExe & " /AutoIt3ExecuteScript " & chr(34) & $sFileName & chr(34)) ; chr(34) is " If $iPID = 0 Then MsgBox($MB_TOPMOST, "Run issue : $iPID = 0 , @error = " & @error, $sFileName) EndIf EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>Example ;============================================== Func _Doubleton($sTitle) If WinExists($sTitle) Then Local $iChoice = Msgbox(BitOr($MB_YESNO, $MB_DEFBUTTON2, $MB_ICONQUESTION, $MB_TOPMOST), $sTitle, _ "This script is already running. Launch another instance ?") If $iChoice = $IDNO Then Return True EndIf AutoItWinSetTitle($sTitle) ; remember the AutoIt window is always hidden EndFunc ;==>_Doubleton1 point -
Ok, this is what it is: au3stripper.exe requires the au3stripper.dat as that contains required input for it and these aren't in the program as a design choice at the time. It comes with the installer or is part of the standard dowloadlink zipfile for au3stripper. The Beta directory contains updated files to the standard installer, and this file isn't updated. General advice: Don't cherry-pick anything from there when you aren't sure what the consequences are.1 point
-
math puzzle
argumentum reacted to orbs for a topic
thank you @Musashi. that was indeed the case. i removed a few old screenshots from old forum posts. now i have ~4MB free... will use them for a good cause 🙂 @argumentum thank you for the reminder, i missed to upload the icon... update in first post. also, can i safely presume you do not have MS-Office installed? your screenshot shows an unexpected character for "New Puzzle" (2nd blue from the top, compare to my screenshot on the first post). this is because it uses the "Wingdings 3" font. the other characters use the "Webdings" or "Wingdings" fonts, shipped with Windows; however "Wingdings 2" and "Wingdings 3" fonts are shipped with other MS products, notably Office. you obviously do not have that font installed; hence i conclude i need to be more meticulous in my choice of fonts... and... that hell of a mess occasionally referred to as "DPI" came over for a visit. i scripted the app in a 150% DPI, just tested it on 100% and 125%, the results are horid. so i'll need to delve into that one as well...1 point -
...so, what's in Au3Stripper.dat you asked @WildByDesign, ok, Functionname,Parameter to check,0=check for function/1=check for Variable adlibenable,1,0 adlibregister,1,0 adlibunregister,1,0 call,1,0 dllcallbackregister,1,0 eval,1,1 guictrlregisterlistviewsort,2,0 guictrlsetonevent,2,0 guiregistermsg,2,0 guisetonevent,2,0 hotkeyset,2,0 isdeclared,1,1 objevent,2,0 onautoitexitregister,1,0 onautoitexitunregister,1,0 opt,2,0 traysetonevent,2,0 trayitemsetonevent,2,0 @Jos, that file, as far as I remember, is never touched/edited by users. Therefore it always uses the default values. Would it be a good idea to ignore it's absence if not found given that anyways a user has no idea of the benefit of changing it ( if there is any ) ? We only use it for AutoIt. ( tho for what I see, it could be use for other coding languages too, hence the file to get the values from )1 point
-
I have been using v5 beta for many months now and have had zero issues on my machine. Thank you for everything, by the way. So I decided to update my GitHub Actions workflow from the old SciTE4AutoIt3 to the latest SciTE4AutoIt3_vsc build that I use on my machine. The workflow uses the /S silent switch to install it. The problem is with the following: - ### C:\Program Files (x86)\AutoIt3\SciTE\Au3Stripper\Au3Stripper.dat missing... Please get it from the website to make sure the Au3Stripper will work correctly. I don't understand why Au3Stripper would specifically be looking for the Au3Stripper.dat file within C:\Program Files (x86)\ when it really should be looking in LocalAppData. But I also don't understand why the old SciTE4AutoIt3 did not have this issue. Is there anywhere that I can tell Au3Stripper where to look for this file? If it's available to download somewhere as a standalone file, I could download/copy the file to wherever it is looking for it.1 point
-
AutoIt Snippets
argumentum reacted to Nine for a topic
In this thread it was discussed about fading out a label from dark to white. So I suggested to use an ownerdraw label to perform such a task. After a bit of searching, I did not find good example, on this forum, of doing it with a label. So there you go : ; From Nine #include <WinAPIDiag.au3> #include <GDIPlus.au3> #include <GUIConstants.au3> ; Blend - Fade - Text - OWNERDRAW - label Opt("MustDeclareVars", True) Global Const $tagDRAWITEMSTRUCT = "uint CtlType;uint CtlID;uint itemID;uint itemAction;uint itemState;hwnd hwndItem;hwnd hDC;" & $tagRECT & ";ulong_ptr itemData;" Global Const $SS_OWNERDRAW = 0x0D Example() Func Example() _GDIPlus_Startup() Local $hGUI = GUICreate("Example", 400, 200, -1, -1, $WS_OVERLAPPEDWINDOW) GUISetBkColor(0xFFFF00) Local $idLabel = GUICtrlCreateLabel("", 75, 20, 250, 40, $SS_OWNERDRAW) GUIRegisterMsg($WM_DRAWITEM, WM_DRAWITEM) GUISetState() While True Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $idLabel ConsoleWrite("Label was clicked" & @CRLF) EndSwitch WEnd _GDIPlus_Shutdown() EndFunc ;==>Example Func WM_DRAWITEM($hWnd, $iMsg, $wParam, $lParam) Local $tData = DllStructCreate($tagDRAWITEMSTRUCT, $lParam) Local $hGraphic = _GDIPlus_GraphicsCreateFromHDC($tData.hdc) Local $hBrush = _GDIPlus_LineBrushCreate(0, 20, $tData.right, 20, 0xFF606060, 0xFFFFFFFF) Local $hFormat = _GDIPlus_StringFormatCreate() _GDIPlus_StringFormatSetAlign($hFormat, 1) Local $hFamily = _GDIPlus_FontFamilyCreate("Arial") Local $hFont = _GDIPlus_FontCreate($hFamily, 28, 2) Local $tLayout = _GDIPlus_RectFCreate(0, Int(($tData.bottom - 40) / 2), $tData.right, 40) Local $aInfo = _GDIPlus_GraphicsMeasureString($hGraphic, "AutoIt Rulez !", $hFont, $tLayout, $hFormat) _GDIPlus_GraphicsClear($hGraphic, 0xFFFF0000) _GDIPlus_GraphicsDrawStringEx($hGraphic, "AutoIt Rulez !", $hFont, $aInfo[0], $hFormat, $hBrush) _GDIPlus_StringFormatDispose($hFormat) _GDIPlus_FontFamilyDispose($hFamily) _GDIPlus_FontDispose($hFont) _GDIPlus_BrushDispose($hBrush) _GDIPlus_GraphicsDispose($hGraphic) Return $GUI_RUNDEFMSG EndFunc ;==>WM_DRAWITEM1 point -
Yes forgot to set the select icon, just modify the line : _GUICtrlTreeView_AddChild($idTreeView, $h1, "App", $idxApp, $idxApp)1 point
-
math puzzle
SOLVE-SMART reacted to argumentum for a topic
1 point -
#include <GUIConstants.au3> #include <GuiTreeView.au3> #include <GuiImageList.au3> GUICreate("Icon Test", 300, 300) Local $idTreeView = GUICtrlCreateTreeView(10, 10, 280, 280) GUISetState() Local $hImageList = _GUIImageList_Create(16, 16, 5, 3) Local $idxFolder = _GUIImageList_AddIcon($hImageList, "shell32.dll", 4) Local $idxApp = _GUIImageList_AddIcon($hImageList, "shell32.dll", 2) _GUICtrlTreeView_SetNormalImageList(GUICtrlGetHandle($idTreeView), $hImageList) Local $h1 = _GUICtrlTreeView_Add($idTreeView, 0, "Category", $idxFolder) _GUICtrlTreeView_AddChild($idTreeView, $h1, "App", $idxApp) While 1 If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop WEnd Win10.1 point
-
JSON UDF in pure AutoIt
WildByDesign reacted to SOLVE-SMART for a topic
I guess the FileWrite action that you described (README.md file) is necessary for the understanding of the cascade ".json --> AutoIt structure --> .json", yes ✅ . I also believe the JSON object manipulation was meant to be described ⚠ . The array/map handling of the JSON object, was maybe unclear. Once it's manipulated, the write to file action is quite simple (as you already mentioned). I won't be able to submit a PR (pull request) as a suggestion anytime soon, so here are just my brief thoughts on the matter. You already use "example.json" in the examples file "JSON-Test.au3". So I would extend the file by an example (with the example.json") for the topic above. Besides that @AspirinJunkie, thanks for the crazy improvements (impressive). Good work as usually 😁 . Best regards Sven1 point -
Another AutoIt extension for Visual Studio Code
seadoggie01 reacted to genius257 for a topic
It was semi-manually, since i also needed to add parameter types and return types. 😅 semi, because i used my inline suggestions from my windsurf AI vscode extension to speed things up. That might be why the text is wrong at some places Edit: I've updated the summary for the two functions mentioned. It will be available with next version 😉1 point -
time taken to convert Array to Safearray UBound: 10308 Array_Split: 3.59900051094329 to_Safearray: 10.3791479145815 Now if you delete the code within __Array_to_SafeArray then the time taken just to pass the data through COM objects.... UBound: 10308 Array_Split: 3.74493431229134 to_Safearray: 9.39925668250824 <<============ So it's an AutoIt internal thing; you have to ask Jon. Example code: #include "SafeArray.au3" #include "ArrayPointer UDF.au3" __Example_0A() Func __Example_0A() $s = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris pharetra tristique felis at dapibus. Vivamus odio lorem, feugiat ut porttitor ac, vehicula sed diam. Donec facilisis quam vitae quam sollicitudin tempus. Quisque ligula sapien, convallis in enim quis, porttitor bibendum lacus. Aenean sollicitudin sit amet augue hendrerit tristique. Nam non est sollicitudin lorem semper tempus ac id tellus. Ut id urna sed justo maximus condimentum ut sed nibh. Integer sit amet consectetur leo. Ut consectetur, nisl eget placerat dignissim, quam dolor rutrum lectus, nec sollicitudin nunc ipsum quis turpis. Maecenas venenatis vel neque vitae aliquam. Etiam id elit quis arcu blandit luctus id ac mauris. Etiam cursus bibendum ultricies. Morbi vitae pellentesque eros, at ullamcorper neque. Duis luctus semper euismod. Etiam vel dui sit amet ante faucibus lacinia non et ante. Quisque id mauris ultrices, congue dui vitae, semper justo. Quisque a placerat metus, vitae ultrices massa. Nunc iaculis faucibus quam quis tincidunt. Integer suscipit ullamcorper felis, eu porttitor nibh sodales ut. Aenean quis fermentum nisl. Maecenas vestibulum hendrerit dolor ac ornare. Mauris vulputate nulla ut nunc ultricies faucibus. Vestibulum ligula enim, vestibulum vitae mauris in, vehicula aliquet nibh. Nunc viverra erat massa, nec scelerisque lacus posuere quis. Maecenas nec neque facilisis, malesuada urna a, iaculis sem. Donec volutpat eget enim nec tempus. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Pellentesque vitae est elementum, feugiat ligula sit amet, porttitor turpis. Aliquam erat volutpat. Quisque id luctus leo. Vestibulum egestas, nibh id euismod semper, sem tellus dictum metus, nec ullamcorper tellus nisi a sapien. Nunc rutrum, mauris eu lacinia tincidunt, velit augue interdum massa, eu porta odio massa ac ipsum. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Curabitur semper sed dolor ut vulputate. Cras cursus odio eu felis tristique, non fermentum tellus bibendum. Mauris laoreet mattis blandit. Morbi eget viverra diam. Nulla a venenatis enim, vitae ullamcorper nisi. Cras feugiat felis id orci sagittis rhoncus. Proin congue tempor urna id viverra. Aliquam scelerisque leo sit amet justo laoreet pulvinar. Integer risus enim, viverra at tortor nec, egestas rutrum massa. Cras id velit imperdiet, elementum ante sit amet, tincidunt nunc. In facilisis mi a suscipit mollis. Donec ornare ante quis sodales vestibulum. Phasellus eget tellus erat. Sed pellentesque eleifend mauris vel malesuada. Quisque orci felis, fringilla vel tellus et, vestibulum efficitur lacus. Nullam dictum ligula non faucibus fermentum. Pellentesque dignissim, velit in scelerisque luctus, lacus arcu fermentum nulla, vel sodales nibh tortor in elit. Curabitur ut orci varius, scelerisque lectus volutpat, posuere turpis. Integer efficitur arcu nec ornare lobortis. Fusce lobortis, odio ut sodales pulvinar, neque nisl eleifend tortor, in dignissim ipsum purus nec nunc. Vivamus auctor lectus volutpat nunc congue sollicitudin nec eu nisl. Cras elementum auctor ligula, et egestas augue pharetra eu. Nam fermentum condimentum finibus. Aliquam a suscipit sem. Cras pretium neque nec ullamcorper aliquet. Sed vitae condimentum est. Curabitur mattis posuere rhoncus. Sed accumsan, quam nec mollis faucibus, velit odio ornare velit, sit amet fermentum enim." $s = $s & $s & $s $hTime_A = TimerInit() $aArray = StringSplit($s, "", 2) ConsoleWrite(" UBound: " & UBound($aArray)&@CRLF) ConsoleWrite(" Array_Split: " & TimerDiff($hTime_A)&@CRLF) Local $t_SAobj Local $o_SAobj = __SafeArray_Dummy_Obj($t_SAobj) $hTime_B = TimerInit() Local $psa $o_SAobj.Array_to_SafeArray($aArray, $psa) SafeArrayUnaccessData( $psa ) ConsoleWrite(" to_Safearray: " & TimerDiff($hTime_B)&@CRLF) SafeArrayDestroy($psa) $o_SAobj = 0 __Delete_SafeArray_ObjectFromTag( $t_SAobj ) EndFunc for ArrayPointer UDF => https://www.autoitscript.com/forum/topic/213008-array-pointer/1 point
-
AutoIt v3.3.17.1 Beta View File 3.3.17.1 (July 08, 2025) (Beta) AutoIt: UDFs: - Fixed: Typo in variable name in Date.au3 introduced in previous beta. 3.3.17.0 (June 29, 2025) (Beta) AutoIt: - Changed: Windows 7/Server 2008 is now the minimum OS version required due to dev environment changes. - Added #3891: DllCall() performance optimisation. - Added: Standard Windows Fonts List for Win10/Win11. - Added #3906: GUICtrlCreateXXX creation in example assign to $idXXX to reflect Ctrl type. - Added: FileGetAttrib() retrieve Join folder (J) as created by FileCreateNTFSLink(). - Added: Split WindowsConstants.u3 in WindowsNotifsConstants.au3, WindowsStylesConstants.au3 and WindowsSysColor.au3. - Added: #3984: GUICtrlSetGraphic() doc precision. - Fixed: Doc Chr(0) handling inside functions. - Fixed #3923: Doc typo in "Send Key List". - Fixed: Regression #3135 handle leak (Thanks Nano, Rudi, Nine). - Fixed #3925: Doc With ... EndWith using DllStruct Type. - Fixed: Links in Tutorials example code (thanks argumentum). Au3info: - Added: Display mouse coordinate mode. - Fixed #3917: Crash under Win7. SciTE-Lite: - Fixed: Folding Fix for #Preprocessor foldblock when followed by a CommentBlock. UDFs: - Added: script examples when running under Win11 with new notepad.exe. - Added: _GUICtrlTreeView_GetItemByIndex() can retrieve handle of the list of main item ($hItem= -1). - Added: _IsPressed() can be called with numeric value as in "WinAPIsvkeysConstants.au3". - Added #3909: _DebugReportData() to report Array column formatted. - Added: libExamples referring MemoWrite() now refer to _MemoWrite() defined in Extras\HelpFileInternals.au3. - Added: _WinAPI_WaitSystemIdle(), _WinAPI_QueryDiskUsage(), _WinAPI_QueryProcessorUsage(), _WinAPI_QueryProcessCycleTime() - Added: Doc _WinAPI_GetWindowSubclass() example (Thanks pixelSearch). - Added: _WinAPI_GetKeyboardLayout() default value for the running thread. - Added: _WinAPI_GetUserDefaultLCID() example. - Added: _WinAPI_GetKeyboardLayoutLocale(). - Added: _WinAPI_GetKeyboardState() example (Thanks AutoXenon). - Added #3932: Try to use file in HelpFile\Extras instead of @ScriptDir. - Added #3934: _WinAPI_SetTimer() example. - Added: _IsPressed() can wait on one of several keys. - Added: _WinAPI_SendInput(). - Added #3960: _Div() integer division. - Added #3963: _WinAPI_OpenEvent(). - Added: _GDIPlus_ImageSaveToFile() doc precision for compression level. - Added: _WinAPI_GetCursorSize() and _WinAPI_SetCursorSize(). - Added: $FOLDERID_Documents Constants in APIShellExConstants.au3. - Added: Support _GUIToolTip*() to be used to external process. - Added: Support _GUICtrlHeader*() to be used to external process. - Added: Support _GUICtrlStatusBar*() to be used to external process. - Added #3988: _WinAPI_GetSystemPowerStatus() return Battery status saver. - Added #3985: _ArrayDisplay() + $WS_EX_TOPMOST. - Added #3991: _SQLite_ForeignKeys() and Add a parameter in _SQLite_Open() to set it also. - Added #3990: _IsPressed() return in @extended if the key is still pressed. - Added: _DebugSetup(..., 1) does not interact with script being debug, Report infos copied to clipboard - Added: _WinAPI_SetWindowTheme() example to demonstrate Checkbox or Radio controls coloring. - Added #3997: _WinAPI_RegisterShellHookWindow() example improvement. - Added #3999: _WinAPI_OemToChar() performance improvement. - Added #3946: _ChooseFont() updated defaults (thanks argumentum). - Added: _DateDiff(), _DateAdd() using array for [days, hours, minutes, seconds]. - Added: _DebugSetup() Type 6, same as 1 but a timeout to close the report log windows. - Fixed #3894: _WinAPI_GetProcessName() returns incorrect result when process ID is invalid. - Fixed: "Then SetError()" in several standard UDF. - Fixed #3921: Missing _GUICtrlStatusBar_SetParts() examples. - Fixed: Doc typo $GPIP_ERR* >> $GDIP_ERR*. - Fixed #3926: _GUICtrlTreeView_SetChildren() not set/reset chidren flag. - Fixed: _WinAPI_DisplayStruct() elements containing chr(124). - Fixed #3945: StringRegExp() /s include VT. - Fixed #3949: _ArrayDisplay() does show multiple subscript of an array. - Fixed #3954: links in libfunction constants. - Fixed: missing doc description $iSubItem = - 1 in _GUICtrlListView_SetItemText(). - Fixed #3959: _WinAPI_ShellUserAuthenticationDlg() example. - Fixed #3975: unrelated link in Pcre doc. - Fixed #3903: _GuiCtrlTab_GetItem() does work on external process. - Fixed #3992: _WinAPI_DwmSetWindowAttribute() does not support all MSDN attributes. - Fixed #4001: _GUICtrlListView_*() example ($tagNMITEMACTIVATE). - Fixed #4003: _ArrayPush() doc precision. - Fixed: _GUICtrlButton_SetSplitInfo() example crash. - Fixed: Support of Notepad under Win11 for _DebugSetup(). - Fixed #4022: Various doc duplicated words. - Fixed #4031: _DebugArrayDisplay() buttons display. - Fixed: _DebugArrayDisplay() not executed if @error on entering ($ARRAYDISPLAY_CHECKERROR if no display wanted on @error). - Fixed #4033: _DateTimeSplit() setting $aTimePart[0] whem no time defined. - Fixed #4024: _DebugSetup(,, 5) (notepad window) not working under Windows 11. - Fixed: _WinAPI_IsElevated() @extended return value (Thanks Argumentum). - Fixed #4039: _GUICtrlTreeView_Delete() with $hWnd. - Fixed #4038: _GUICtrlRichEdit_StreamToFile() extra new paragraph. - Fixed #4029: _Date_Time_SystemTimeToDateTimeStr() Wrong output. - Fixed #4040: _GUICtrlRichEdit_SetZoom() parameter limitation bug. - Fixed #4041: _GUICtrlStatusBar_SetIcon() not shown. Submitter Jon Submitted 07/08/2025 Category Beta1 point
-
1 point
-
_Array2D_Binary Search
VenusProject2 reacted to BrewManNH for a topic
I encountered the speed of using _ArrayBinarySearch while working on a project of mine. I had previously been using _ArraySearch in the project to find duplicate items in 2 different arrays so that I could add the contents of the second array to the first one without having any duplicates. Unfortunately, the arrays I was searching had over 4000 rows in each, and using _ArraySearch to search through this took about 30-60 seconds on average on my older laptop. I had been using _ArraySearch because _ArrayBinarySearch only worked on 1D arrays and one of my arrays was 2D. My workaround for this was to create a temporary array that only contained the column of the 2D array I actually needed to search through, sorted it, and then used _ArrayBinarySearch to do my search for duplicates. This took the search time down to well under 1 second on average to go through the 2 arrays. So, you're probably wondering why I'm mentioning this. Well, the reason I had to go through the array gymnastics was because of the 1D array limitations of _ArrayBinarySearch. I figured that I would look at the function and see if I could tweak it to use search a sorted 2D array, and that's exactly what I've done. The function below has the same caveats as the original search function, the column that you're searching on MUST be sorted or you will end up with undefined results. It's actually very simple to use this function and it can be used in place of _ArrayBinarySearch because it will search both 1D and 2D arrays using the same code as the original function did, I just modified it to work with 2 dimensional arrays. Here's the code and a quickly thrown together example of how I used it to search 2 arrays for duplicate items. #include <Array.au3> Global $Array1[4000], $Array2[3999][2], $TLV_Array[4000], $Count = 0 For $I = 0 To 3999 For $X = 1 To 30 $Array1[$I] &= Chr(Random(65, 90, 1)) Next Next For $I = 0 To 3998 $Array2[$I][0] = $Array1[$I] $Array2[$I][1] = $I Next _ArraySort($Array2) _ArrayDisplay($Array2, "Sorted $Array2 by first column") $Timer = TimerInit() For $I = UBound($Array1) - 1 To 0 Step -1 Local $Read1 = $Array1[$I] Local $DelDup = _Array2D_BinarySearch($Array2, $Read1, 0) If $DelDup = -1 Then $TLV_Array[$Count] = $Array1[$I] $Count += 1 EndIf Next ReDim $TLV_Array[$Count] $Array1 = $TLV_Array ConsoleWrite("@@ (" & @ScriptLineNumber & ") : Time to check for duplicate files: " & Int(TimerDiff($Timer)) / 1000 & @CRLF) _ArrayDisplay($Array1, "$Array1 after deleting the duplicates") ; #FUNCTION# ==================================================================================================================== ; Name...........: _Array2D_BinarySearch ; Description ...: Uses the binary search algorithm to search through a 1 or 2-dimensional array. ; Syntax.........: _Array2D_BinarySearch(Const ByRef $avArray, $vValue[, $iColumn = 0[, $iStart = 0[, $iEnd = 0]]]) ; Parameters ....: $avArray - Array to search ; $vValue - Value to find ; $iColumn - [optional] Which column to search on [Default = First (0) column] ; $iStart - [optional] Index of array to start searching at [Default = start of array] ; $iEnd - [optional] Index of array to stop searching at [Default = end of array] ; Return values .: Success - Index that value was found at ; Failure - -1, sets @error to: ; |1 - $avArray is not an array ; |2 - $vValue outside of array's min/max values ; |3 - $vValue was not found in array ; |4 - $iStart is greater than $iEnd ; |5 - $iColumn is greater than actual number of columns ; |6 - $avArray has too many dimensions ; Author ........: Jos van der Zande <jdeb at autoitscript dot com> ; Modified.......: Ultima - added $iEnd as parameter, code cleanup ; Modified.......: BrewManNH - added ability to search a 2D array ; Remarks .......: When performing a binary search on an array of items, the contents of the column being searched MUST be ; sorted before the search is done, otherwise undefined results will be returned. ; Related .......: _ArrayFindAll, _ArraySearch, _ArrayBinarySearch ; Link ..........: ; Example .......: Yes ; =============================================================================================================================== Func _Array2D_BinarySearch(Const ByRef $avArray, $vValue, $iColumn = 0, $iStart = 0, $iEnd = 0) If UBound($avArray, 0) > 2 Then Return SetError(6, 0, -1) Local $i2D = False If UBound($avArray, 0) > 1 Then $i2D = True EndIf If UBound($avArray, 2) < $iColumn Then Return SetError(5, 0, -1) If Not IsArray($avArray) Then Return SetError(1, 0, -1) Local $iUBound = UBound($avArray) - 1 ; Bounds checking If $iEnd < 1 Or $iEnd > $iUBound Then $iEnd = $iUBound If $iStart < 0 Then $iStart = 0 If $iStart > $iEnd Then Return SetError(4, 0, -1) Local $iMid = Int(($iEnd + $iStart) / 2) If Not $i2D Then If $avArray[$iStart] > $vValue Or $avArray[$iEnd] < $vValue Then Return SetError(2, 0, -1) ; Search While $iStart <= $iMid And $vValue <> $avArray[$iMid] If $vValue < $avArray[$iMid] Then $iEnd = $iMid - 1 Else $iStart = $iMid + 1 EndIf $iMid = Int(($iEnd + $iStart) / 2) WEnd If $iStart > $iEnd Then Return SetError(3, 0, -1) ; Entry not found Return $iMid Else If $avArray[$iStart][$iColumn] > $vValue Or $avArray[$iEnd][$iColumn] < $vValue Then Return SetError(2, 0, -1) ; Search While $iStart <= $iMid And $vValue <> $avArray[$iMid][$iColumn] If $vValue < $avArray[$iMid][$iColumn] Then $iEnd = $iMid - 1 Else $iStart = $iMid + 1 EndIf $iMid = Int(($iEnd + $iStart) / 2) WEnd If $iStart > $iEnd Then Return SetError(3, 0, -1) ; Entry not found Return $iMid EndIf EndFunc ;==>_Array2D_BinarySearch1 point