this-is-me Posted March 10, 2014 Share Posted March 10, 2014 I want to be able to make a single-access timer (actually a timeout). This code works in 32-bit, but hard crashes in 64-bit: #include <Timers.au3> _Timer_SetTimer(WinGetHandle(AutoItWinGetTitle()), 6000, "__TimeoutCall") While Sleep(1000) WEnd Func __TimeoutCall($hwnd, $Msg, $iIDTimer, $dwTime) ;#forceref $hWnd, $Msg, $iIDTimer, $dwTim _Timer_KillTimer($hwnd, $iIDTimer) ;First, kill our own timer so that we don't repeat the commands. ConsoleWrite("timer") EndFunc Although I am aware that I can use Adlib functions, I would prefer to use Timers.au3. Is killing the timer inside the timer callback function a no-no for some reason? Who else would I be? Link to comment Share on other sites More sharing options...
guinness Posted March 10, 2014 Share Posted March 10, 2014 I read MSDN and can't see why it should crashing. Though still think it's best to use native functions over UDFs. UDF List: _AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples... Updated: 22/04/2018 Link to comment Share on other sites More sharing options...
funkey Posted March 10, 2014 Share Posted March 10, 2014 This is a bug. Problem is DllCallbackFree from within callback function. This is a Workaround. #include <Timers.au3> Global $hCallBack = DllCallbackRegister("__TimeoutCall", "none", "hwnd;int;uint_ptr;dword") DllCall("user32.dll", "uint_ptr", "SetTimer", "hwnd", AutoItWinGetTitle(), "uint_ptr", 1001, "uint", 5000, "ptr", DllCallbackGetPtr($hCallBack)) Global $bCallbackFree = False While Sleep(1000) If $bCallbackFree Then DllCallbackFree($hCallBack) WEnd Func __TimeoutCall($hwnd, $Msg, $iIDTimer, $dwTime) ;#forceref $hWnd, $Msg, $iIDTimer, $dwTim DllCall("user32.dll", "bool", "KillTimer", "hwnd", $hwnd, "uint_ptr", $iIDTimer) $bCallbackFree = True ConsoleWrite("timer" & @LF) EndFunc Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
jguinch Posted March 10, 2014 Share Posted March 10, 2014 I had this problem once... I solved the problem by killing the timer outside the timer function. (equivalent to that funkey offers) #include <Timers.au3> $kill = False $timer = _Timer_SetTimer(WinGetHandle(AutoItWinGetTitle()) , 6000, "__TimeoutCall") While Sleep(1000) If $kill Then _Timer_KillTimer(WinGetHandle(AutoItWinGetTitle()), $timer) ;First, kill our own timer so that we don't repeat the commands. WEnd Func __TimeoutCall($hwnd, $Msg, $iIDTimer, $dwTime) ;#forceref $hWnd, $Msg, $iIDTimer, $dwTim $kill = True ConsoleWrite("timer") EndFunc Spoiler Network configuration UDF, _DirGetSizeByExtension, _UninstallList Firefox ConfigurationArray multi-dimensions, Printer Management UDF Link to comment Share on other sites More sharing options...
guinness Posted March 10, 2014 Share Posted March 10, 2014 Well, well. UDF List: _AdapterConnections() • _AlwaysRun() • _AppMon() • _AppMonEx() • _ArrayFilter/_ArrayReduce • _BinaryBin() • _CheckMsgBox() • _CmdLineRaw() • _ContextMenu() • _ConvertLHWebColor()/_ConvertSHWebColor() • _DesktopDimensions() • _DisplayPassword() • _DotNet_Load()/_DotNet_Unload() • _Fibonacci() • _FileCompare() • _FileCompareContents() • _FileNameByHandle() • _FilePrefix/SRE() • _FindInFile() • _GetBackgroundColor()/_SetBackgroundColor() • _GetConrolID() • _GetCtrlClass() • _GetDirectoryFormat() • _GetDriveMediaType() • _GetFilename()/_GetFilenameExt() • _GetHardwareID() • _GetIP() • _GetIP_Country() • _GetOSLanguage() • _GetSavedSource() • _GetStringSize() • _GetSystemPaths() • _GetURLImage() • _GIFImage() • _GoogleWeather() • _GUICtrlCreateGroup() • _GUICtrlListBox_CreateArray() • _GUICtrlListView_CreateArray() • _GUICtrlListView_SaveCSV() • _GUICtrlListView_SaveHTML() • _GUICtrlListView_SaveTxt() • _GUICtrlListView_SaveXML() • _GUICtrlMenu_Recent() • _GUICtrlMenu_SetItemImage() • _GUICtrlTreeView_CreateArray() • _GUIDisable() • _GUIImageList_SetIconFromHandle() • _GUIRegisterMsg() • _GUISetIcon() • _Icon_Clear()/_Icon_Set() • _IdleTime() • _InetGet() • _InetGetGUI() • _InetGetProgress() • _IPDetails() • _IsFileOlder() • _IsGUID() • _IsHex() • _IsPalindrome() • _IsRegKey() • _IsStringRegExp() • _IsSystemDrive() • _IsUPX() • _IsValidType() • _IsWebColor() • _Language() • _Log() • _MicrosoftInternetConnectivity() • _MSDNDataType() • _PathFull/GetRelative/Split() • _PathSplitEx() • _PrintFromArray() • _ProgressSetMarquee() • _ReDim() • _RockPaperScissors()/_RockPaperScissorsLizardSpock() • _ScrollingCredits • _SelfDelete() • _SelfRename() • _SelfUpdate() • _SendTo() • _ShellAll() • _ShellFile() • _ShellFolder() • _SingletonHWID() • _SingletonPID() • _Startup() • _StringCompact() • _StringIsValid() • _StringRegExpMetaCharacters() • _StringReplaceWholeWord() • _StringStripChars() • _Temperature() • _TrialPeriod() • _UKToUSDate()/_USToUKDate() • _WinAPI_Create_CTL_CODE() • _WinAPI_CreateGUID() • _WMIDateStringToDate()/_DateToWMIDateString() • Au3 script parsing • AutoIt Search • AutoIt3 Portable • AutoIt3WrapperToPragma • AutoItWinGetTitle()/AutoItWinSetTitle() • Coding • DirToHTML5 • FileInstallr • FileReadLastChars() • GeoIP database • GUI - Only Close Button • GUI Examples • GUICtrlDeleteImage() • GUICtrlGetBkColor() • GUICtrlGetStyle() • GUIEvents • GUIGetBkColor() • Int_Parse() & Int_TryParse() • IsISBN() • LockFile() • Mapping CtrlIDs • OOP in AutoIt • ParseHeadersToSciTE() • PasswordValid • PasteBin • Posts Per Day • PreExpand • Protect Globals • Queue() • Resource Update • ResourcesEx • SciTE Jump • Settings INI • SHELLHOOK • Shunting-Yard • Signature Creator • Stack() • Stopwatch() • StringAddLF()/StringStripLF() • StringEOLToCRLF() • VSCROLL • WM_COPYDATA • More Examples... Updated: 22/04/2018 Link to comment Share on other sites More sharing options...
this-is-me Posted March 10, 2014 Author Share Posted March 10, 2014 Thank you all for your suggestions, but I don't think the workaround will work for me. I don't see a way to have this workaround with extremely small timeouts (such as 50 ms) without also having an extremely tight main loop. Please allow me to post my entire code so you can make a recommendation. Here is SetTimeout.au3: expandcollapse popup#include-once #include <Array.au3> #include <Timers.au3> #include "param.au3" Global $g_TimersArray[1][3] Global Enum $g_TimerID, $g_TimerFunc, $g_TimerParam Func _SetTimeout($time, $function, $params = -1) Local $index = ($g_TimersArray[0][0] = "") ? 0 : UBound($g_TimersArray) Local $iIDTimer = _Timer_SetTimer(WinGetHandle(AutoItWinGetTitle()), $time, "__TimeoutCall") If $index <> 0 Then ReDim $g_TimersArray[$index + 1][3] $g_TimersArray[$index][$g_TimerID] = $iIDTimer $g_TimersArray[$index][$g_TimerFunc] = FuncName($function) $g_TimersArray[$index][$g_TimerParam] = $params Return $iIDTimer EndFunc Func _SetTimeoutCancel($iIDTimer) _Timer_KillTimer(WinGetHandle(AutoItWinGetTitle()), $iIDTimer) For $i = 0 To UBound($g_TimersArray) - 1 If $iIDTimer = $g_TimersArray[$i][$g_TimerID] Then If $i = 0 Then $g_TimersArray[0][0] = "" $g_TimersArray[0][1] = "" $g_TimersArray[0][2] = "" Else _ArrayDelete($g_TimersArray, $i) EndIf Return EndIf Next EndFunc Func __TimeoutCall($hwnd, $Msg, $iIDTimer, $dwTime) #forceref $hWnd, $Msg, $iIDTimer, $dwTime _Timer_KillTimer($hwnd, $iIDTimer) ;First, kill our own timer so that we don't repeat the commands. For $i = 0 To UBound($g_TimersArray) - 1 If $iIDTimer = $g_TimersArray[$i][$g_TimerID] Then If Not IsArray($g_TimersArray[$i][$g_TimerParam]) Then Call($g_TimersArray[$i][$g_TimerFunc]) Else Call($g_TimersArray[$i][$g_TimerFunc], $g_TimersArray[$i][$g_TimerParam]) EndIf If $i = 0 Then $g_TimersArray[0][0] = "" $g_TimersArray[0][1] = "" $g_TimersArray[0][2] = "" Else _ArrayDelete($g_TimersArray, $i) EndIf ExitLoop EndIf Next EndFunc And param.au3: #include-once Func param($1=0, $2=0, $3=0, $4=0, $5=0, $6=0, $7=0, $8=0, $9=0, $10=0, $11=0, $12=0, $13=0, $14=0, $15=0, $16=0, $17=0, $18=0, $19=0, $20=0, $21=0, $22=0, $23=0, $24=0, $25=0, $26=0, $27=0, $28=0, $29=0, $30=0, $31=0, $32=0, $33=0, $34=0, $35=0, $36=0, $37=0, $38=0, $39=0, $40=0, $41=0, $42=0, $43=0, $44=0, $45=0, $46=0, $47=0, $48=0, $49=0, $50=0, $51=0, $52=0, $53=0, $54=0, $55=0, $56=0, $57=0, $58=0, $59=0, $60=0, $61=0, $62=0, $63=0, $64=0, $65=0, $66=0, $67=0, $68=0, $69=0, $70=0, $71=0, $72=0, $73=0, $74=0, $75=0, $76=0, $77=0, $78=0, $79=0, $80=0, $81=0, $82=0, $83=0, $84=0, $85=0, $86=0, $87=0, $88=0, $89=0, $90=0, $91=0, $92=0, $93=0, $94=0, $95=0, $96=0, $97=0, $98=0, $99=0, $100=0, $101=0, $102=0, $103=0, $104=0, $105=0, $106=0, $107=0, $108=0, $109=0, $110=0, $111=0, $112=0, $113=0, $114=0, $115=0, $116=0, $117=0, $118=0, $119=0, $120=0, $121=0, $122=0, $123=0, $124=0, $125=0, $126=0, $127=0, $128=0, $129=0, $130=0, $131=0, $132=0, $133=0, $134=0, $135=0, $136=0, $137=0, $138=0, $139=0, $140=0, $141=0, $142=0, $143=0, $144=0, $145=0, $146=0, $147=0, $148=0, $149=0, $150=0, $151=0, $152=0, $153=0, $154=0, $155=0, $156=0, $157=0, $158=0, $159=0, $160=0, $161=0, $162=0, $163=0, $164=0, $165=0, $166=0, $167=0, $168=0, $169=0, $170=0, $171=0, $172=0, $173=0, $174=0, $175=0, $176=0, $177=0, $178=0, $179=0, $180=0, $181=0, $182=0, $183=0, $184=0, $185=0, $186=0, $187=0, $188=0, $189=0, $190=0, $191=0, $192=0, $193=0, $194=0, $195=0, $196=0, $197=0, $198=0, $199=0, $200=0, $201=0, $202=0, $203=0, $204=0, $205=0, $206=0, $207=0, $208=0, $209=0, $210=0, $211=0, $212=0, $213=0, $214=0, $215=0, $216=0, $217=0, $218=0, $219=0, $220=0, $221=0, $222=0, $223=0, $224=0, $225=0, $226=0, $227=0, $228=0, $229=0, $230=0, $231=0, $232=0, $233=0, $234=0, $235=0, $236=0, $237=0, $238=0, $239=0, $240=0, $241=0, $242=0, $243=0, $244=0, $245=0, $246=0, $247=0, $248=0, $249=0, $250=0, $251=0, $252=0, $253=0, $254=0, $255=0) Local $arr[@NumParams + 1] = ["CallArgArray"] For $i = 1 To @NumParams $arr[$i] = Eval($i) Next Return $arr EndFunc An example of how this might be used is as follows: #include "SetTimeout.au3" ToolTip("Hi, there") _SetTimeout(1000, ToolTip, param('')) Sleep(5000) Now the above example is minimal. The real meat of how I use this function on a daily basis is in "breaking out" of functions that are already callbacks, and must return quickly. Partial code example (I can post FolderMonitor.au3 if someone wants it): #include "FolderMonitor.au3" #include "SetTimeout.au3" _Folder_Monitor("C:\", FolderChange, $SHCNE_RENAMEFOLDER) Func FolderChange($iEvent, $sFolder, $sFolderNew) Switch $iEvent Case $SHCNE_RENAMEFOLDER ; Apparently, the shell waits for this function to complete before moving on with the rename, so we need to return quickly. ; For this reason, we exit from this function by setting a timer to come back to what we really want to do. _SetTimeout(50, RenameFolder, param($sFolder, $sFolderNew)) EndSwitch EndFunc ;==>FolderChange Based on the workarounds given, I don't see how I can modify SetTimeout.au3 so that execution of functions only happens once, and no more. Especially when I don't want to have a while loop in SetTimeout.au3 Does anyone have suggestions for using such a workaround in relation to this code? Who else would I be? Link to comment Share on other sites More sharing options...
KaFu Posted March 10, 2014 Share Posted March 10, 2014 Well, and idea that comes to my mind... - Use a scripting.dictionary object (stack) to store that changes - In FolderChange() add the change to the stack and call a processing function with AdlibRegister() - Process the stack's items in the processing function and only unregister the Adlib (from within the adlib function) if the stack's size = 0 at the end of the function OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
this-is-me Posted March 10, 2014 Author Share Posted March 10, 2014 KaFu, would using a global array not be faster and less overhead than using a scripting dictionary? Who else would I be? Link to comment Share on other sites More sharing options...
funkey Posted March 10, 2014 Share Posted March 10, 2014 (edited) You could start an adlib before leaving __TimeoutCall() to release the $hCallback. But before you have to change _Timer_KillTimer() to not free the DllCallback. and save the $hCallback in a global variable. Edited March 10, 2014 by funkey Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
this-is-me Posted March 10, 2014 Author Share Posted March 10, 2014 Thanks, funkey. I was afraid something like that would be necessary. Looks like I'll be reworking most UDF functions for x64 compatibility before long (lol). Altough I would rather hope that the bugs just get fixed. Since this is, indeed, a bug, should I submit it to trac or something? Who else would I be? Link to comment Share on other sites More sharing options...
KaFu Posted March 10, 2014 Share Posted March 10, 2014 In my experience the scripting dictionary object is really fast and stack operations are easy to implement, but you're right, a global array should work all the same (though you would need to "emulate" the stack character for the array with some extra code). OS: Win10-22H2 - 64bit - German, AutoIt Version: 3.3.16.1, AutoIt Editor: SciTE, Website: https://funk.eu AMT - Auto-Movie-Thumbnailer (2022-Nov-26) BIC - Batch-Image-Cropper (2023-Apr-01) COP - Color Picker (2009-May-21) DCS - Dynamic Cursor Selector (2024-Feb-16) HMW - Hide my Windows (2018-Sep-16) HRC - HotKey Resolution Changer (2012-May-16) ICU - Icon Configuration Utility (2018-Sep-16) SMF - Search my Files (2023-Jun-03) - THE file info and duplicates search tool SSD - Set Sound Device (2017-Sep-16) Link to comment Share on other sites More sharing options...
funkey Posted March 10, 2014 Share Posted March 10, 2014 (edited) Try this SetTimeout.au3 (I can't test, because I'm on 3.3.8.1) Edit: You have to add the new global variable to your $g_TimersArray, if you start more than one timeout. And then you Need another global variable to tell the adlib function which callback should be released. No nice solution. expandcollapse popup#include-once #include <Array.au3> #include <Timers.au3> #include "param.au3" Global $g_TimersArray[1][3] Global $g_hCallback ;new line Global Enum $g_TimerID, $g_TimerFunc, $g_TimerParam Func _SetTimeout($time, $function, $params = -1) Local $index = ($g_TimersArray[0][0] = "") ? 0 : UBound($g_TimersArray) Local $iIDTimer = _Timer_SetTimer(WinGetHandle(AutoItWinGetTitle()), $time, "__TimeoutCall") If $index <> 0 Then ReDim $g_TimersArray[$index + 1][3] $g_TimersArray[$index][$g_TimerID] = $iIDTimer $g_TimersArray[$index][$g_TimerFunc] = FuncName($function) $g_TimersArray[$index][$g_TimerParam] = $params $g_hCallback = $_Timers_aTimerIDs[$_Timers_aTimerIDs[0][0]][2] ;new line $_Timers_aTimerIDs[$_Timers_aTimerIDs[0][0]][2] = 0 ;new line (to prevent _Timer_KillTimer to free the DllCallback) Return $iIDTimer EndFunc Func _SetTimeoutCancel($iIDTimer) _Timer_KillTimer(WinGetHandle(AutoItWinGetTitle()), $iIDTimer) For $i = 0 To UBound($g_TimersArray) - 1 If $iIDTimer = $g_TimersArray[$i][$g_TimerID] Then If $i = 0 Then $g_TimersArray[0][0] = "" $g_TimersArray[0][1] = "" $g_TimersArray[0][2] = "" Else _ArrayDelete($g_TimersArray, $i) EndIf Return EndIf Next EndFunc Func __TimeoutCall($hwnd, $Msg, $iIDTimer, $dwTime) #forceref $hWnd, $Msg, $iIDTimer, $dwTime _Timer_KillTimer($hwnd, $iIDTimer) ;First, kill our own timer so that we don't repeat the commands. For $i = 0 To UBound($g_TimersArray) - 1 If $iIDTimer = $g_TimersArray[$i][$g_TimerID] Then If Not IsArray($g_TimersArray[$i][$g_TimerParam]) Then Call($g_TimersArray[$i][$g_TimerFunc]) Else Call($g_TimersArray[$i][$g_TimerFunc], $g_TimersArray[$i][$g_TimerParam]) EndIf If $i = 0 Then $g_TimersArray[0][0] = "" $g_TimersArray[0][1] = "" $g_TimersArray[0][2] = "" Else _ArrayDelete($g_TimersArray, $i) EndIf ExitLoop EndIf Next AdlibRegister("__TimeoutCall_Release", 100) ;new line EndFunc ;new function Func __TimeoutCall_Release() AdlibUnRegister("__TimeoutCall_Release") DllCallbackFree($g_hCallback) EndFunc Edited March 10, 2014 by funkey Programming today is a race between software engineers striving tobuild bigger and better idiot-proof programs, and the Universetrying to produce bigger and better idiots.So far, the Universe is winning. Link to comment Share on other sites More sharing options...
this-is-me Posted March 10, 2014 Author Share Posted March 10, 2014 Thanks, funkey. Since your suggestion, I decided to replace the KillTimer with a local copy that does what I need. Here is my finalized code that works perfectly: expandcollapse popup#include-once #include <Array.au3> #include <Timers.au3> #include "param.au3" Global $g_TimersArray[1][3] Global Enum $g_TimerID, $g_TimerFunc, $g_TimerParam Global $g_TimerCallbacks[1] Func _SetTimeout($time, $function, $params = -1) Local $index = ($g_TimersArray[0][0] = "") ? 0 : UBound($g_TimersArray) Local $iIDTimer = _Timer_SetTimer(WinGetHandle(AutoItWinGetTitle()), $time, "__Timeout_Call") If $index <> 0 Then ReDim $g_TimersArray[$index + 1][3] $g_TimersArray[$index][$g_TimerID] = $iIDTimer $g_TimersArray[$index][$g_TimerFunc] = FuncName($function) $g_TimersArray[$index][$g_TimerParam] = $params Return $iIDTimer EndFunc Func _SetTimeout_Cancel($iIDTimer) __Timeout_KillTimer(WinGetHandle(AutoItWinGetTitle()), $iIDTimer) For $i = 0 To UBound($g_TimersArray) - 1 If $iIDTimer = $g_TimersArray[$i][$g_TimerID] Then If $i = 0 Then $g_TimersArray[0][0] = "" $g_TimersArray[0][1] = "" $g_TimersArray[0][2] = "" Else _ArrayDelete($g_TimersArray, $i) EndIf Return EndIf Next EndFunc Func __Timeout_Call($hwnd, $Msg, $iIDTimer, $dwTime) #forceref $hWnd, $Msg, $iIDTimer, $dwTime __Timeout_KillTimer($hwnd, $iIDTimer) ;First, kill our own timer so that we don't repeat the commands. For $i = 0 To UBound($g_TimersArray) - 1 If $iIDTimer = $g_TimersArray[$i][$g_TimerID] Then If Not IsArray($g_TimersArray[$i][$g_TimerParam]) Then Call($g_TimersArray[$i][$g_TimerFunc]) Else Call($g_TimersArray[$i][$g_TimerFunc], $g_TimersArray[$i][$g_TimerParam]) EndIf If $i = 0 Then $g_TimersArray[0][0] = "" $g_TimersArray[0][1] = "" $g_TimersArray[0][2] = "" Else _ArrayDelete($g_TimersArray, $i) EndIf ExitLoop EndIf Next EndFunc Func __Timeout_KillTimer($hWnd, $iTimerID) Local $aResult[1] = [0], $hCallBack = 0, $iUBound = UBound($_Timers_aTimerIDs) - 1 For $x = 1 To $iUBound If $_Timers_aTimerIDs[$x][0] = $iTimerID Then If IsHWnd($hWnd) Then $aResult = DllCall("user32.dll", "bool", "KillTimer", "hwnd", $hWnd, "uint_ptr", $_Timers_aTimerIDs[$x][1]) Else $aResult = DllCall("user32.dll", "bool", "KillTimer", "hwnd", $hWnd, "uint_ptr", $_Timers_aTimerIDs[$x][0]) EndIf If @error Or $aResult[0] = 0 Then Return SetError(@error, @extended, False) $hCallBack = $_Timers_aTimerIDs[$x][2] If $hCallBack <> 0 Then Local $index = ($g_TimerCallbacks[0] = "") ? 0 : UBound($g_TimerCallbacks) If $index <> 0 Then ReDim $g_TimerCallbacks[$index + 1] $g_TimerCallbacks[$index] = $hCallBack AdlibRegister(__Timeout_Free, 6000) ; Assume 6 seconds is enough time for the __Timeout_Call'd function to run. EndIf For $i = $x To $iUBound - 1 $_Timers_aTimerIDs[$i][0] = $_Timers_aTimerIDs[$i + 1][0] $_Timers_aTimerIDs[$i][1] = $_Timers_aTimerIDs[$i + 1][1] $_Timers_aTimerIDs[$i][2] = $_Timers_aTimerIDs[$i + 1][2] Next ReDim $_Timers_aTimerIDs[UBound($_Timers_aTimerIDs - 1)][3] $_Timers_aTimerIDs[0][0] -= 1 ExitLoop EndIf Next Return $aResult[0] <> 0 EndFunc ;==>_Timer_KillTimer Func __Timeout_Free() AdlibUnRegister(__Timeout_Free) For $i = UBound($g_TimerCallbacks) - 1 To 0 Step -1 ; Reverse so that when we _ArrayDelete we won't go out of bounds DllCallbackFree($g_TimerCallbacks[$i]) If $i = 0 Then $g_TimerCallbacks[0] = '' Else _ArrayDelete($g_TimerCallbacks, $i) EndIf Next EndFunc Who else would I be? Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now