kurtykurtyboy Posted August 26, 2022 Share Posted August 26, 2022 (edited) I stumbled across this recent support thread on using multiple "stopwatches", so I thought I would have a little fun and make a full-featured stopwatch object using AutoItObject_Internal.au3 by @genius257. It's not super useful, but who doesn't like a full UDF for the simplest of tasks? This is more of a proof of concept and is not meant to be extremely accurate or reliable, but I'm still open to suggestions if anyone has any ideas for improvement. The stopwatch has the following methods: start: start (or restart) the timer and reset the accumulated timer value stop: stop/pause the timer lap: return the time since the last time lap was called or since the timer was started reset: stop and reset the timer elapsed: get the time since the last reset or since the timer was started To use a stopwatch, simply create a new object and start the timer. You can then retrieve the total elapsed time or the current lap time. #include "ObjStopwatch.au3" $oStopwatch1 = _ObjStopwatch() $oStopwatch1.start() sleep(500) consolewrite("Lap time: " & $oStopwatch1.lap() & @CRLF) sleep(500) consolewrite("Total time: " & $oStopwatch1.elapsed() & @CRLF) The .elapsed method has 1 optional parameter to set the return formatting. ; Syntax.........: _ObjStopwatch_elapsed ( [$iFormat = 0] ) ; Parameters ....: $iFormat = desired format ; - 0 = ms with decimal (same as TimerDiff()) ; - 1 = hh:mm:ss ; - 2 = hh:mm:ss:0ms ; - 3 = hh:mm:ss.0 Similarly, the .lap method has 2 optional parameters. By passing False as the 2nd parameter, you can poll the current lap time without triggering a new lap. ; Syntax.........: _ObjStopwatch_lap ( [ $iFormat = 0 [, $bNewLap = True ]] ) ; Parameters ....: $iFormat = desired format ; - 0 = ms with decimal (same as TimerDiff()) ; - 1 = hh:mm:ss ; - 2 = hh:mm:ss:0ms ; - 3 = hh:mm:ss.0 ; $bNewLap = Return the current lap time, and reset lap timer The real power of this UDF (really all thanks for AutoItObject_Internal) is the ability to create as many Stopwatch objects as you want, which you are then free to start and stop independently. #include "ObjStopwatch.au3" $oStopwatch1 = _ObjStopwatch() $oStopwatch2 = _ObjStopwatch() $oStopwatch3 = _ObjStopwatch() $oStopwatch4 = _ObjStopwatch() $oStopwatch1.start() $oStopwatch2.start() Sleep(500) $oStopwatch1.stop() Sleep(500) consolewrite("Stopwatch 1: " & $oStopwatch1.elapsed() & @CRLF) consolewrite("Stopwatch 2: " & $oStopwatch2.elapsed() & @CRLF) Lastly, here is a simple GUI example for recording the lap times of 2 different stopwatches. Spoiler expandcollapse popup#include <WindowsConstants.au3> #include <GUIConstantsEx.au3> #include <GuiListView.au3> #include "ObjStopwatch.au3" Opt("GUIOnEventMode", 1) $AutoItError = ObjEvent("AutoIt.Error", "ErrFunc") ; Install a custom error handler Func ErrFunc($oError) ConsoleWrite("!>COM Error !" & @CRLF & "!>" & @TAB & "Number: " & Hex($oError.Number, 8) & @CRLF & "!>" & @TAB & "Windescription: " & StringRegExpReplace($oError.windescription, "\R$", "") & @CRLF & "!>" & @TAB & "Source: " & $oError.source & @CRLF & "!>" & @TAB & "Description: " & $oError.description & @CRLF & "!>" & @TAB & "Helpfile: " & $oError.helpfile & @CRLF & "!>" & @TAB & "Helpcontext: " & $oError.helpcontext & @CRLF & "!>" & @TAB & "Lastdllerror: " & $oError.lastdllerror & @CRLF & "!>" & @TAB & "Scriptline: " & $oError.scriptline & @CRLF) EndFunc ;==>ErrFunc Global $ListView_1, $ListView_2 ;create 2 stopwatch objects Global $oStopwatch1 = _ObjStopwatch() Global $oStopwatch2 = _ObjStopwatch() _main() Func _main() Local $hGUI = GUICreate("MyGUI", 437, 259, 772, 292) GUISetOnEvent($GUI_EVENT_CLOSE, "_onExit") Local $label1 = GUICtrlCreateLabel("Stopwatch 1:", 5, 4, 81, 18) Local $label_time1 = GUICtrlCreateLabel("00:00:00:000", 78, 4, 81, 18) Local $button_start1 = GUICtrlCreateButton("Start", 5, 21, 51, 21) GUICtrlSetOnEvent(-1, _onStart1) Local $button_lap1 = GUICtrlCreateButton("Lap", 56, 21, 51, 21) GUICtrlSetOnEvent(-1, _onLap1) Local $button_stop1 = GUICtrlCreateButton("Stop", 107, 21, 51, 21) GUICtrlSetOnEvent(-1, _onStop1) Local $button_reset = GUICtrlCreateButton("Reset", 158, 21, 51, 21) GUICtrlSetOnEvent(-1, _onReset1) $ListView_1 = GUICtrlCreateListView("Lap Time", 7, 48, 200, 201) _GUICtrlListView_SetColumnWidth(-1, 0, 145) Local $label2 = GUICtrlCreateLabel("Stopwatch 2:", 230, 4, 81, 18) Local $label_time2 = GUICtrlCreateLabel("00:00:00:000", 303, 4, 81, 18) Local $button_start2 = GUICtrlCreateButton("Start", 230, 21, 51, 21) GUICtrlSetOnEvent(-1, _onStart2) Local $button_lap2 = GUICtrlCreateButton("Lap", 281, 21, 51, 21) GUICtrlSetOnEvent(-1, _onLap2) Local $button_stop2 = GUICtrlCreateButton("Stop", 332, 21, 51, 21) GUICtrlSetOnEvent(-1, _onStop2) Local $button_reset2 = GUICtrlCreateButton("Reset", 383, 21, 51, 21) GUICtrlSetOnEvent(-1, _onReset2) $ListView_2 = GUICtrlCreateListView("Lap Time", 232, 48, 200, 201) _GUICtrlListView_SetColumnWidth(-1, 0, 145) GUISetState(@SW_SHOWNORMAL) ;some variables to hold values Local $Time1, $Time2, $Lap1, $Lap2 Local $prevTime1, $prevTime2, $displayTimer = TimerInit() While 1 $Time1 = $oStopwatch1.elapsed(2) $Time2 = $oStopwatch2.elapsed(2) ;timer to slow down label flicker If TimerDiff($displayTimer) > 100 Then If $Time1 <> $prevTime1 Then GUICtrlSetData($label_time1, $Time1) $prevTime1 = $Time1 EndIf If $Time2 <> $prevTime2 Then GUICtrlSetData($label_time2, $Time2) $prevTime2 = $Time2 EndIf $displayTimer = TimerInit() EndIf Sleep(10) WEnd EndFunc ;==>_main Func _onStart1() $oStopwatch1.start() EndFunc ;==>_onStart1 Func _onLap1() GUICtrlCreateListViewItem($oStopwatch1.lap(2), $ListView_1) EndFunc ;==>_onLap1 Func _onStop1() $oStopwatch1.stop() EndFunc ;==>_onStop1 Func _onReset1() $oStopwatch1.reset() _GUICtrlListView_DeleteAllItems($ListView_1) EndFunc ;==>_onReset1 Func _onStart2() $oStopwatch2.start() EndFunc ;==>_onStart2 Func _onLap2() GUICtrlCreateListViewItem($oStopwatch2.lap(2), $ListView_2) EndFunc ;==>_onLap2 Func _onStop2() $oStopwatch2.stop() EndFunc ;==>_onStop2 Func _onReset2() $oStopwatch2.reset() _GUICtrlListView_DeleteAllItems($ListView_2) EndFunc ;==>_onReset2 Func _onExit() GUIDelete() Exit EndFunc ;==>_onExit Updated 2022-08-29: ObjStopwatch.au3 Fixed time formatting issue. Prerequisite: AutoItObject_Internal.au3 is required. Download [HERE]. Edited August 30, 2022 by kurtykurtyboy update noellarkin and Gianni 2 Link to comment Share on other sites More sharing options...
Gianni Posted August 26, 2022 Share Posted August 26, 2022 hey, I thought I'd do the same thing using @genius257's own AutoItObject_Internal Thanks for saving me the trouble.... Nice work of course, and also an interesting usage example for the AutoItObject_Internal. Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
Gianni Posted August 26, 2022 Share Posted August 26, 2022 ... trying the examples I'm experiencing "crashes" ... I do further tests ... Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
funkey Posted August 26, 2022 Share Posted August 26, 2022 Works fine for me on 3.3.14.5. Thanks 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...
kurtykurtyboy Posted August 26, 2022 Author Share Posted August 26, 2022 @Gianni Actually, I saw a few random crashes when testing it but it was so few and far between that I chalked it up to hitting F5 too fast between runs. I ended up putting the COM error handler in the example to try and catch that crash, but I couldn't get it to happen again. Well I tried getting it to crash again and it took about 20 tries but it finally crashed. It showed the GUI briefly then disappeared and gave the following exit code. I'm not sure how to troubleshoot since it doesn't appear to be a COM error and it's not a normal error that is reported in the console - just a silent crash. For now I'm adding a bunch of log messages to see where it might be crashing. I'm using v3.3.16.0. Link to comment Share on other sites More sharing options...
genius257 Posted August 27, 2022 Share Posted August 27, 2022 Hi @kurtykurtyboy. That error code translates to 0xC0000005 (Access Violation). It occurs when non accessible data access is attempted. Mostly it happens when freed memory is accessed and the now possibly random data end up being used as a pointer to a non accessible memory pointer reference. If it's my code only at fault, it is a tedious, but easy process of finding the faulty code. However i have found that some VERY specific cases can result in AutoIt3 crashing, that seems to be an issue with AutoIt3. see this issue i have in another project of mine for example. Trouble is confirming that is is not my code being the culprit is hard when it comes to memory manipulation and complex scenarios. TheDcoder 1 My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser Link to comment Share on other sites More sharing options...
Gianni Posted August 29, 2022 Share Posted August 29, 2022 I still did a small test using the "Simple Gui Example" script present in the spoiler of the first post, and I modified this portion of code While 1 ConsoleWrite("Debug 1" & @CRLF) $Time1 = $oStopwatch1.elapsed(2) ConsoleWrite("Debug 2" & @CRLF) $Time2 = $oStopwatch2.elapsed(2) ConsoleWrite("Debug 3" & @CRLF) ;timer to slow down label flicker If TimerDiff($displayTimer) > 100 Then If $Time1 <> $prevTime1 Then GUICtrlSetData($label_time1, $Time1) $prevTime1 = $Time1 EndIf ConsoleWrite("Debug 4" & @CRLF) If $Time2 <> $prevTime2 Then GUICtrlSetData($label_time2, $Time2) $prevTime2 = $Time2 EndIf $displayTimer = TimerInit() EndIf Sleep(10) ConsoleWrite("Debug 5" & @CRLF) WEnd where I added some consolewrite to see where the script crashes and it seems that the line that he does not like is $time2 = $stopwatch2.elaPsed (2) I tried the script on two different computers (both with Win10 Pro x64) and I receive two different crash type: This on a computer: Debug 1 Debug 2 Debug 3 Debug 5 Debug 1 Debug 2 !>17:13:05 AutoIt3.exe ended.rc:-1073741819 +>17:13:05 AutoIt3Wrapper Finished. >Exit code: 3221225477 Time: 8.258 And this on another computer: Debug 1 Debug 2 Debug 3 Debug 5 Debug 1 !>17:23:36 AutoIt3.exe ended.rc:255 +>17:23:36 AutoIt3Wrapper Finished. >Exit code: 255 Time: 12.38 ... just for the record ... Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
genius257 Posted August 29, 2022 Share Posted August 29, 2022 Tested the example and did not experience a crash. OS:WIN_7/Service Pack 1 CPU:X64 OS:X64 AUTOIT3: 3.3.16.0 @kurtykurtyboy it seems your _ObjStopwatch_formatTime with $iFormat = 2 needs one less leading zero My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser Link to comment Share on other sites More sharing options...
kurtykurtyboy Posted August 29, 2022 Author Share Posted August 29, 2022 (edited) Ah, you're right. Don't I feel silly now! I guess I was thinking 1,000ms in 1sec, so 4 digits. 🤦♂️ I'll go ahead and fix that... Fixed! Edited August 30, 2022 by kurtykurtyboy genius257 1 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