Jump to content

OnKeyPress event and timer issue


Razi
 Share

Recommended Posts

Can you help solve the problem in code? The problem is that in the following code, when I press backspace in any Input control or any other keyboard button, the value is returned back. For example: when I want to change the value 127 in the input control and I erase the number 7 with the backspace button, the number becomes 127 again. But I need the number to change when any keyboard button is pressed.

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <Timers.au3>
#Include <WinAPIEx.au3>
#include <Misc.au3>

#Region ### START Koda GUI section ### Form=
Local $Form1 = GUICreate("Form1", 658, 401, 192, 124)
Local $aInput[135], $c = 0
Global $nMsg

For $y = 0 To 8
  For $a = 0 To 14
    $aInput[$c] = GUICtrlCreateInput('Input' & $a+1 + $y*15, 26+$y*53, 31+$a*22 , 52, 21)
    $c += 1
  Next
Next

Global $timedelay = _Timer_Init() ;Start delay timer

GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

Global $timersec = 2000


While 1
    $nMsg = GUIGetMsg()
    local $inp = $nMsg - $aInput[0]
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $aInput[0] To $aInput[UBound($aInput) - 1]
            $timersec = 3600000
            ConsoleWrite($timersec & @CRLF)
            ConsoleWrite($inp & @CRLF)
            $val = Number(GUICtrlRead($nMsg))

        If $val <> 0 And _IsPressed("0D") Then
            $val = Number(GUICtrlRead($nMsg))
            local $inp = $nMsg - $aInput[0]
            GUICtrlSetData($aInput[$inp], $inp)
            ConsoleWrite($val & @CRLF)
            $timersec = 2000
        EndIf
        ;ConsoleWrite("Input " & $nMsg - $aInput[0] & " has been modified" & @CRLF)
    EndSwitch

    If _Timer_Diff($timedelay) > $timersec Then
            For $x = 0 To 134
            GUICtrlSetData($aInput[$x], $x)
            Next
        $timedelay = _Timer_Init()   ;Reset delay timer
    EndIf
WEnd

Func WM_COMMAND($hWinHandle, $iMsg, $wParam, $lParam)
    If _WinAPI_HiWord($wParam) = $EN_CHANGE Then
        Switch _WinAPI_LoWord($wParam)
            Case $aInput[0] To $aInput[UBound($aInput) - 1]
            local $inp = $nMsg - $aInput[0]
                ConsoleWrite($inp & @CRLF)
        EndSwitch
    EndIf
EndFunc

Without changing the following part of the code:

If _Timer_Diff($timedelay) > $timersec Then
            For $x = 0 To 134
            local $number = 132* Int($x / 15) + Mod($x,15)
            GUICtrlSetData($aInput[$x], $x)
            Next
        $timedelay = _Timer_Init()   ;Reset delay timer
    EndIf

In general, I want to pause the timer when any button on the keyboard was pressed in any Input GUI control, but the code manages to execute this part of the code: GUICtrlSetData($aInput[$x], $x) , although it should not execute it after pressing the keyboard button in any Input GUI control.

Edited by Razi
Link to comment
Share on other sites

 To tell the truth, I didn't really understand what exactly the script does, but I know that here you had to calculate an offset , Maybe other things need adjusting  :huh2:

in the line Case $aInput[0] To $aInput[UBound($aInput) - 1] 

you have to calculate one offset, in this case + 3 ,   because the $aInput[0] =  GUIGetMsg() = 3

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#Include <Timers.au3>
#Include <WinAPIEx.au3>
#include <Misc.au3>
#include <Debug.au3>

#Region ### START Koda GUI section ### Form=
Local $Form1 = GUICreate("Form1", 658, 401, 192, 124)
Local $aInput[135], $c = 0
Global $nMsg

For $y = 0 To 8
  For $a = 0 To 14
    $aInput[$c] = GUICtrlCreateInput('Input' & $a+1 + $y*15, 26+$y*53, 31+$a*22 , 52, 21)
    $c += 1
  Next
Next

ConsoleWrite("you have to calculate one offset, in this case +" & $aInput[0] & @CRLF)

Global $timedelay = _Timer_Init() ;Start delay timer

GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

Global $timersec = 2000


While 1
    $nMsg = GUIGetMsg()
    local $inp = $nMsg - $aInput[0]
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $aInput[0] + 3 To  $aInput[0] + 3 + $aInput[UBound($aInput) - 1] ;if $nMsg = $aInput[0] + 3
            $timersec = 3600000
            ConsoleWrite($timersec & @CRLF)
            ConsoleWrite($inp & @CRLF)
            ConsoleWrite("$nMsg=" & $nMsg & @CRLF)
            $val = Number(GUICtrlRead($nMsg))

        If $val <> 0 And _IsPressed("0D") Then
            $val = Number(GUICtrlRead($nMsg))
            local $inp = $nMsg - $aInput[0]
            GUICtrlSetData($aInput[$inp], $inp)
;~             ConsoleWrite($val & @CRLF)
            $timersec = 2000
        EndIf
        ;ConsoleWrite("Input " & $nMsg - $aInput[0] & " has been modified" & @CRLF)
    EndSwitch

    If _Timer_Diff($timedelay) > $timersec Then
            For $x = 0 To 134
            GUICtrlSetData($aInput[$x], $x)
            Next
        $timedelay = _Timer_Init()   ;Reset delay timer
    EndIf
WEnd

Func WM_COMMAND($hWinHandle, $iMsg, $wParam, $lParam)
    If _WinAPI_HiWord($wParam) = $EN_CHANGE Then
        Switch _WinAPI_LoWord($wParam)
            Case $aInput[0] To $aInput[UBound($aInput) - 1]
            local $inp = $nMsg - $aInput[0]
;~                 ConsoleWrite($inp & @CRLF)
        EndSwitch
    EndIf
EndFunc

 

I know that I know nothing

Link to comment
Share on other sites

I also am a bit confused on what your goal is, but I think that the issue is you default to resetting all values every 2 seconds. Every time you press Backspace, you're saying that if your timer was started more than 2 seconds ago, do your GUICtrlSetData($aInput[$x], $x). Add some logging to your TimerDiff section and you can see when that happens. Also, why are you using <Timers.au3> instead of the normal TimerInit() and TimerDiff()?

 

So, why are you setting $timersec = 3600000 and then if Backspace is pressed, back down to $timersec = 2000? You're enabling it so that if you press backspace in 2s or less (since the timer is already running, the timer is not reset, only its goal was changed) it'll reset all values. 

 

I think I have something closer to what you want. As long as you type something in a box every < 2s it will not replace all values to default. If you take longer than 2s, it'll replace everything back to default.

#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Timers.au3>
#include <WinAPIEx.au3>
#include <Misc.au3>
#include <Debug.au3>

#Region ### START Koda GUI section ### Form=
Local $Form1 = GUICreate("Form1", 658, 401, 192, 124)
Local $aInput[135], $c = 0
Global $nMsg

For $y = 0 To 8
    For $a = 0 To 14
        $aInput[$c] = GUICtrlCreateInput('Input' & $a + 1 + $y * 15, 26 + $y * 53, 31 + $a * 22, 52, 21)
        $c += 1
    Next
Next

ConsoleWrite("you have to calculate one offset, in this case +" & $aInput[0] & @CRLF)

Global $timedelay = _Timer_Init() ;Start delay timer

GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

Global $timersec = 2000


While 1
    $nMsg = GUIGetMsg()
    Local $inp = $nMsg - $aInput[0]
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $aInput[0] + 3 To $aInput[0] + 3 + $aInput[UBound($aInput) - 1]  ;if $nMsg = $aInput[0] + 3
;~          $timersec = 3600000
;~          ConsoleWrite($timersec & @CRLF) ; There's no point in logging this, you just set it to 3600000
;~          ConsoleWrite($inp & @CRLF)
;~          ConsoleWrite("$nMsg=" & $nMsg & @CRLF)
            $val = Number(GUICtrlRead($nMsg))

;~          ConsoleWrite('$val (GUICtrlRead($nMsg)): ' & $val & @CRLF)

;~          If $val <> 0 And _IsPressed("0D") Then
;~              $val = Number(GUICtrlRead($nMsg))
;~              Local $inp = $nMsg - $aInput[0]
;~              GUICtrlSetData($aInput[$inp], $inp)
;~             ConsoleWrite($val & @CRLF)
;~              $timersec = 2000
;~          EndIf
            ;ConsoleWrite("Input " & $nMsg - $aInput[0] & " has been modified" & @CRLF)
    EndSwitch

    If _Timer_Diff($timedelay) > $timersec Then
        ConsoleWrite('_Timer_Diff($timedelay): ' & Round(_Timer_Diff($timedelay), 2) & ', $timersec: ' & $timersec & @CRLF)
        For $x = 0 To 134
            GUICtrlSetData($aInput[$x], $x)
        Next
        $timedelay = _Timer_Init()   ;Reset delay timer
    EndIf
WEnd

Func WM_COMMAND($hWnd, $iMsg, $wParam, $lParam)
    Local $nNotifyCode = _WinAPI_HiWord($wParam)
    Local $iId = _WinAPI_LoWord($wParam)
    Local $hCtrl = $lParam

    If $nNotifyCode = $EN_CHANGE Then
        ConsoleWrite('$nNotifyCode = $EN_CHANGE, $hCtrl: ' & $hCtrl & ', $iId: ' & $iId & @CRLF)
        Switch $iId
            Case $aInput[0] To $aInput[UBound($aInput) - 1]
;~              Local $inp = $nMsg - $aInput[0] + 3
                If _IsPressed("0D") <> 1 Then $timedelay = _Timer_Init()   ;Reset delay timer
;~                 ConsoleWrite($inp & @CRLF)
        EndSwitch
    EndIf
EndFunc   ;==>WM_COMMAND

 

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

4 hours ago, ioa747 said:

I didn't really understand what exactly the script does

I want the timer to stop when I press any keyboard button in the input field and not reset the value.

 

3 hours ago, mistersquirrle said:

why are you setting $timersec = 3600000

This gives the effect of a timer pause and the values in the input fields are not reset (not updated). Here, I want to stop updating the values.

 

3 hours ago, mistersquirrle said:

then if Backspace is pressed, back down to $timersec = 2000?

If  _IsPressed("0D") Then : When the "Enter" button is pressed, then update the values every 2 seconds again.

I wanted to achieve an effect when I press any button in the input field, then do not update the values. And when I press the "Enter" button, then update the values again.

But for some reason this condition is executed (If _Timer_Diff($timedelay) > $timersec Then) , although it should not be executed, after pressing any button.

I don't know if this function is needed at all: Func WM_COMMAND($hWinHandle, $iMsg, $wParam, $lParam)

Edited by Razi
Link to comment
Share on other sites

1 minute ago, Razi said:

If  _IsPressed("0D") Then : When the "Enter" button is pressed, then update the values every 2 seconds again.

My mistake, I knew it was Enter but I got it confused with your comments about backspace so mixed them up.

 

2 minutes ago, Razi said:

I want the timer to stop when I press any keyboard button in the input field and not reset the value.

Did you try the code that I posted? That's exactly what it does in mine

2 minutes ago, Razi said:

This gives the effect of a timer pause and the values in the input fields are not reset (not updated). Here, I want to stop updating the values.

Setting $timersec = 3600000 (aka 1 hour) does NOT pause the timer, it only extends the time until the timer reaches it goal. If you want to actually 'pause' the timer, you need to just set $timedelay = 0 (destroys the timer), and when you want to 'unpause' the timer, set it to $timedelay = _Timer_Init(). This way you can keep your $timersec to the value you want and have a better 'pause' on the timer. For a more accurate pause, you'd want to do something like this:
 

#include-once
#include <Timers.au3>

Global $ghTimer
Global $giPauseTime, $giCount = 0
Global $giTimerTimeoutMs = 2 * 1000
Global $giTimerUnpausedTime = $giTimerTimeoutMs
Global $ghTotalTimer = TimerInit() ; Used to track the total time

_StartTimer($ghTimer)
Sleep(100)
ConsoleWrite('$ghTimer after 100 ms: ' & Round(_Timer_Diff($ghTimer), 2) & ' ms' & @CRLF)
Sleep(1000)
ConsoleWrite('$ghTimer after additional 1000 ms: ' & Round(_Timer_Diff($ghTimer), 2) & ' ms' & @CRLF)
_PauseTimer($ghTimer)
Sleep(1000)
_ResumeTimer($ghTimer)
ConsoleWrite('$ghTimer after paused for 1000 ms: ' & Round(_Timer_Diff($ghTimer), 2) & ' ms, time remaining after pause: ' & $giTimerUnpausedTime & @CRLF)

Do
    Sleep(10)
    $giCount += 1
    If Mod($giCount, 10) = 0 Then ConsoleWrite('$ghTimer waiting until ' & Ceiling($giTimerUnpausedTime) & ': ' & Round(_Timer_Diff($ghTimer), 2) & ' ms' & @CRLF)
Until _Timer_Diff($ghTimer) >= $giTimerUnpausedTime
ConsoleWrite('Total time to run: ' & Round(TimerDiff($ghTotalTimer), 2) & ' ms' & @CRLF)

Func _PauseTimer(ByRef $hTimer)
    Local $iTimerMs = _Timer_Diff($hTimer)
    $giTimerUnpausedTime = $giTimerUnpausedTime - $iTimerMs
    ConsoleWrite('Timer paused at: ' & Round($iTimerMs, 2) & ' ms, time remaining: ' & $giTimerUnpausedTime & @CRLF)
    $hTimer = 0 ; Destory/stop the timer
    Return $giTimerUnpausedTime
EndFunc   ;==>_PauseTimer

Func _ResumeTimer(ByRef $hTimer)
    $hTimer = _Timer_Init()
    Return 1
EndFunc   ;==>_ResumeTimer

Func _StartTimer(ByRef $hTimer)
    $hTimer = _Timer_Init()
    $giTimerUnpausedTime = $giTimerTimeoutMs
EndFunc   ;==>_StartTimer

But I don't think that you want to actually 'pause' the timer, it would make more sense to reset the timer on interaction, in my opinion. That's what my code in the previous post was doing.

We ought not to misbehave, but we should look as though we could.

Link to comment
Share on other sites

19 hours ago, mistersquirrle said:

Did you try the code that I posted?

Yes, I tried, but the code just resets $timedelay to zero. I need when at least 1 button was pressed in Input field, then stop/pause timer. I just want to change value in Input field, for that I need to stop updating the values. And start to update values after "Enter" button was pressed in Input field.

 

19 hours ago, mistersquirrle said:

you need to just set $timedelay = 0 (destroys the timer)

Unfortunately, it didn't help. Or I don't know where to paste it.

Why the developers of Autoit didn't included the stop/pause timer function? It's so inconvenient to use a timer.

 

On 2/19/2023 at 7:33 PM, ioa747 said:

you have to calculate one offset, in this case + 3 ,   because the $aInput[0] =  GUIGetMsg() = 3

Thanks, that's a helpful note.

Edited by Razi
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...