Page 1 of 2

Time threshold...

Posted: 15 Jun 2021, 00:20
by akirofe
Hi guys!

Could you please kindly help me with the problems I'm having:

I have the codes below:

a & s::
send {WheelDown}{WheelDown}{WheelDown}{WheelDown}{WheelDown}{WheelDown}{WheelDown}{WheelDown}{WheelDown}
return

Problem:
Without AHK on, when we type "a" and "s" fast, eg. in the word "pleASe", usually the "s" goes down while the "a" is still down, but somehow it still works and type "as" for us.
So, could you please show me if there is a "delay" threshold code to apply, so that "a & s" only hotkey to WheelDown when I hold "a" long enough pass the threshold, otherwise if "s" was down right after a, it'll type "as" as normal.

Added: and if "a" is pressed and released without any other keys is pressed in between, then it would type a normal "a" character, and will also work when we hold Shift for a capital "A".

That would help me hugely!!!!

Thank you very much guys!!!!

Re: Time threshold...

Posted: 15 Jun 2021, 08:03
by Rohwedder
Hallo,
only a try:

Code: Select all

$*a::
Send, {Blind}a
KeyWait, a
Return
~a & s::Send,% (A_TimeSincePriorHotkey > 400)?"{Bs}{WheelDown 9}":"{Blind}s"

Re: Time threshold...

Posted: 19 Jun 2021, 20:30
by akirofe
Rohwedder wrote:
15 Jun 2021, 08:03
Hallo,
only a try:

Code: Select all

$*a::
Send, {Blind}a
KeyWait, a
Return
~a & s::Send,% (A_TimeSincePriorHotkey > 400)?"{Bs}{WheelDown 9}":"{Blind}s"
Hi thank you Rohwedder,

I tried but it didn't work :(

Could you please help me a bit more?

Added: and if "a" is pressed and released without any other keys is pressed in between, then it would type a normal "a" character, and will also work when we hold Shift for a capital "A".

Thank you very much Rohwedder!!!

Re: Time threshold...

Posted: 19 Jun 2021, 20:36
by akirofe
Added: and if "a" is pressed and released without any other keys is pressed in between, then it would type a normal "a" character, and will also work when we hold Shift for a capital "A".

Thank you!!!

Re: Time threshold...

Posted: 26 Jun 2021, 07:39
by akirofe
Hi guys,

Anyone...? Please kindly help...

Thank you very much guys!!

Re: Time threshold...

Posted: 30 Jun 2021, 10:10
by safetycar
When I saw this topic the first time I thought on suggesting other alternatives,
but I thought someone else would had something more relevant to say.

Since the topic is still pending...

In the past I tried to do what you are trying , but once you find a workaround for the first issue you have to find a workaround for the workaround, and so on.
Now when I create hotkeys I try to avoid overlapping of functionalities.
I recommend you to think of using context based hotkeys instead, #IfWinActive and other #If variations.
When I make a hotkey for a program I try to reserve it for a single use, unless I can change its context.
I think it's more predictable and easier to use.
I recommend you checking the examples like where it says Variant (Duplicate) Hotkeys
and asking if you have troubles.

Edit: Its likely that you will need to use modifier keys to find less common hotkeys than single letters. Modifier symbols are mencioned in the docs too: Hotkeys.

Re: Time threshold...

Posted: 30 Jun 2021, 20:09
by akirofe
safetycar wrote:
30 Jun 2021, 10:10
When I saw this topic the first time I thought on suggesting other alternatives,
but I thought someone else would had something more relevant to say.

Since the topic is still pending...

In the past I tried to do what you are trying , but once you find a workaround for the first issue you have to find a workaround for the workaround, and so on.
Now when I create hotkeys I try to avoid overlapping of functionalities.
I recommend you to think of using context based hotkeys instead, #IfWinActive and other #If variations.
When I make a hotkey for a program I try to reserve it for a single use, unless I can change its context.
I think it's more predictable and easier to use.
I recommend you checking the examples like where it says Variant (Duplicate) Hotkeys
and asking if you have troubles.

Edit: Its likely that you will need to use modifier keys to find less common hotkeys than single letters. Modifier symbols are mencioned in the docs too: Hotkeys.
Hi Safetycar,

Thank you very much for your help and I understand exactly what you're doing. Unfortunately, there is a solid reason why I need it exactly that way. It is because my work as a CAD drafter involves a lot of mouse clicks AND scroll wheel (to zoom) AND holding down the painful scroll wheel (to pan) AND typing SIMULTANEOUSLY that caused my right's arm-shoulder-neck pains, so I am trying to do all that with the having-little-to-do left hand leaving the right hand just to move the mouse. And constantly "clicking" means using a combination of A S D F where the left fingers already are to save movement is best as the thumb gets tired more quickly on the spacebar, I think God didn't make the thumb for repeative movement as other fingers. And 2 key combination starting with A is best when I tested all options.... :((((

I still hope for a solution... :(( Thank you very much again Safetycar!!!

Re: Time threshold...

Posted: 01 Jul 2021, 10:56
by safetycar
So that you can understand what you're getting into:
Key presses are divided into UP and DOWN events.
When you are trying to type, you will usually press 2 keys at the same time... the as in please might look like {a down} {s down} {a up} {s up}
Not messing the order of your keys is one of the things to have in mind.
And there's also the windows auto-repetition that you have to avoid at the same time:
a & s could appear as {a down} {s down} {s down} {s down} {s down} {s down} {s down} {s down} {s up} {a up}
Even if you take care of your a and s independently, you can get in troubles with the key that comes after the s ("e" for the word please).

So, (again :roll: ) the most I can do is offer you more alternative ideas.
For example, tryng to use CapsLock as modifier key:
(Probably this could be coded in a better way, but I tried to google more stylish attempts and I didn't have luck.)

Code: Select all

; Start of Script and auto-execute section.
SetCapsLockState, % GetKeyState("CapsLock", "T") ? "AlwaysOn" : "AlwaysOff"
return ; End of auto-execute section.
CapsLock:: SetCapsLockState, % GetKeyState("CapsLock", "T") ? "AlwaysOn" : "AlwaysOff"
CapsLock Up::
	if (A_PriorHotkey = "CapsLock")
		SetCapsLockState, % GetKeyState("CapsLock", "T") ? "AlwaysOff" : "AlwaysOn"
return
; The code above is to trigger CapsLock only if it was the only key pressed.
; Below your hotkeys, for example:
CapsLock & a::
	Send, 2
return

There's also a possibility of taking advantage of Lock-Keys' states in this other way, but I doubt of its usefulness for your case.
Anyway you could think of other toggle keys and use them the same way.

Code: Select all

#If (GetKeyState("CapsLock", "T")) ; This could be ScrollLock or NumLock
a::
	Send, 2
return

Re: Time threshold...

Posted: 04 Jul 2021, 07:41
by akirofe
safetycar wrote:
01 Jul 2021, 10:56
So that you can understand what you're getting into:
Key presses are divided into UP and DOWN events.
When you are trying to type, you will usually press 2 keys at the same time... the as in please might look like {a down} {s down} {a up} {s up}
Not messing the order of your keys is one of the things to have in mind.
And there's also the windows auto-repetition that you have to avoid at the same time:
a & s could appear as {a down} {s down} {s down} {s down} {s down} {s down} {s down} {s down} {s up} {a up}
Even if you take care of your a and s independently, you can get in troubles with the key that comes after the s ("e" for the word please).

So, (again :roll: ) the most I can do is offer you more alternative ideas.
For example, tryng to use CapsLock as modifier key:
(Probably this could be coded in a better way, but I tried to google more stylish attempts and I didn't have luck.)

Code: Select all

; Start of Script and auto-execute section.
SetCapsLockState, % GetKeyState("CapsLock", "T") ? "AlwaysOn" : "AlwaysOff"
return ; End of auto-execute section.
CapsLock:: SetCapsLockState, % GetKeyState("CapsLock", "T") ? "AlwaysOn" : "AlwaysOff"
CapsLock Up::
	if (A_PriorHotkey = "CapsLock")
		SetCapsLockState, % GetKeyState("CapsLock", "T") ? "AlwaysOff" : "AlwaysOn"
return
; The code above is to trigger CapsLock only if it was the only key pressed.
; Below your hotkeys, for example:
CapsLock & a::
	Send, 2
return

There's also a possibility of taking advantage of Lock-Keys' states in this other way, but I doubt of its usefulness for your case.
Anyway you could think of other toggle keys and use them the same way.

Code: Select all

#If (GetKeyState("CapsLock", "T")) ; This could be ScrollLock or NumLock
a::
	Send, 2
return
Hi Safetycar,

Thank you very much for your efforts!!!

Unfortunately your alternative solution still won't work in my case :(((

I hope there's a "time threshold" function thingy...

Re: Time threshold...

Posted: 04 Jul 2021, 14:24
by safetycar
Eh...
The closest I could get...
But I will deny having written it.
*drops it and runs away* :wave:

Code: Select all

; Config:
DelayInMs := 500

return 

$a::
	if (A_ThisHotkey = A_PriorHotkey)
		return
	Key_A_Interrupted := False
	Key_A_WaitTick := A_TickCount + DelayInMs
return

$a Up::
	Key_A_WaitTick := 0
	if (!Key_A_Interrupted)
		Send, {Blind}a
return

#If (Key_A_WaitTick && A_TickCount > Key_A_WaitTick)
a & s::
	Key_A_Interrupted := True
	Send, {WheelDown}
	Tooltip, {WheelDown}
return

Re: Time threshold...

Posted: 04 Jul 2021, 20:49
by braunbaer
TH: Time within which "s" following "a" is seen as separate character, in milliseconds

Code: Select all

TH:=300      ; in milliseconds

#if aPressed
~a up::  input

#if
$a::
aPressed:=A_TickCount
input ch, L1
ticks:=A_TickCount-aPressed, aPressed:=0
if (errorlevel="NewInput") {
   send a
   return
   }
if (Ticks>TH) and (ch="s")
   msgbox a & s pressed
else
   send a%ch%
return


Re: Time threshold...

Posted: 10 Jul 2021, 01:03
by akirofe
safetycar wrote:
04 Jul 2021, 14:24
Eh...
The closest I could get...
But I will deny having written it.
*drops it and runs away* :wave:

Code: Select all

; Config:
DelayInMs := 500

return 

$a::
	if (A_ThisHotkey = A_PriorHotkey)
		return
	Key_A_Interrupted := False
	Key_A_WaitTick := A_TickCount + DelayInMs
return

$a Up::
	Key_A_WaitTick := 0
	if (!Key_A_Interrupted)
		Send, {Blind}a
return

#If (Key_A_WaitTick && A_TickCount > Key_A_WaitTick)
a & s::
	Key_A_Interrupted := True
	Send, {WheelDown}
	Tooltip, {WheelDown}
return
Hi, is it me or it didn't work :(( Thank you!!

Re: Time threshold...

Posted: 10 Jul 2021, 02:16
by akirofe
braunbaer wrote:
04 Jul 2021, 20:49
TH: Time within which "s" following "a" is seen as separate character, in milliseconds

Code: Select all

TH:=300      ; in milliseconds

#if aPressed
~a up::  input

#if
$a::
aPressed:=A_TickCount
input ch, L1
ticks:=A_TickCount-aPressed, aPressed:=0
if (errorlevel="NewInput") {
   send a
   return
   }
if (Ticks>TH) and (ch="s")
   msgbox a & s pressed
else
   send a%ch%
return

Hi, is it me or it didn't work :(( Thank you!!

Re: Time threshold...

Posted: 10 Jul 2021, 04:30
by just me
My first attempt to use InputHook(). It might come close:

Code: Select all

#NoEnv
#InstallKeybdHook
Global Treshold := 400
Global PriorKey := ""
Global IsDown := 0
Global Hook := InputHook("L1")
Hook.OnEnd := Func("HookEnded")
Return
; ------------------------------------------------------------------------------
$a::
$+a::
   IsDown := A_TickCount
   PriorKey := InStr(A_ThisHotkey, "+") ? "A" : "a"
   Hook.Start()
   KeyWait, a
   Hook.Stop()
   IsDown := 0
   If (PriorKey <> "") {
      SendInput, %PriorKey%
      PriorKey := ""
   }
Return
; ------------------------------------------------------------------------------
HookEnded(InputHook) {
   EndReason := InputHook.EndReason
   Input := InputHook.Input
   InputHook.Stop()
   If (EndReason = "Max") {
      If (Input = "s") && (IsDown) && ((A_TickCount - IsDown) >= Treshold)
         ToolTip, Bingo:!`nPriorKey: %PriorKey% - Input: %Input%
      Else
         ToolTip, Bongo!`nPriorKey: %PriorKey% - Input: %Input%
   }
   IsDown := 0
   PriorKey := ""
}
; ------------------------------------------------------------------------------
Esc::ExitApp

Re: Time threshold...

Posted: 10 Jul 2021, 06:21
by akirofe
just me wrote:
10 Jul 2021, 04:30
My first attempt to use InputHook(). It might come close:

Code: Select all

#NoEnv
#InstallKeybdHook
Global Treshold := 400
Global PriorKey := ""
Global IsDown := 0
Global Hook := InputHook("L1")
Hook.OnEnd := Func("HookEnded")
Return
; ------------------------------------------------------------------------------
$a::
$+a::
   IsDown := A_TickCount
   PriorKey := InStr(A_ThisHotkey, "+") ? "A" : "a"
   Hook.Start()
   KeyWait, a
   Hook.Stop()
   IsDown := 0
   If (PriorKey <> "") {
      SendInput, %PriorKey%
      PriorKey := ""
   }
Return
; ------------------------------------------------------------------------------
HookEnded(InputHook) {
   EndReason := InputHook.EndReason
   Input := InputHook.Input
   InputHook.Stop()
   If (EndReason = "Max") {
      If (Input = "s") && (IsDown) && ((A_TickCount - IsDown) >= Treshold)
         ToolTip, Bingo:!`nPriorKey: %PriorKey% - Input: %Input%
      Else
         ToolTip, Bongo!`nPriorKey: %PriorKey% - Input: %Input%
   }
   IsDown := 0
   PriorKey := ""
}
; ------------------------------------------------------------------------------
Esc::ExitApp
Thank you very much JustMe!!

Could you please help me as to where should I insert it into my codes below please? Thank you very much again!!

Code: Select all

$a::send a
Shift & a::send A
a & g::return
; a & LCtrl::
; ;;;
a & s::
send {WheelDown}{WheelDown}{WheelDown}			
return
a & d::
send {WheelUp}{WheelUp}
return
a & f::LButton
a & Space::RButton
a & w::Escape
a & e::Delete
; a & r::
; a & 4::
[Mod edit: [code][/code] tags added.]

Re: Time threshold...

Posted: 10 Jul 2021, 07:19
by just me
Maybe:

Code: Select all

HookEnded(InputHook) {
   ...
   If (EndReason = "Max") {
      If (IsDown) && ((A_TickCount - IsDown) >= Treshold) {
         Switch Input {
            Case "s":   ; a & s
               Send ...
            Case "d":   ; a & d
               Send
            Case "f":   ; a & f
               Send ...
            Case " ":   ; a & space
               Send ...
            Case "w":   ; a & w
               Send ...
            Case "e":   ; a & e
               Send ...
            Default:    ; a & anything else
               Send %PriorKey%%Input%
         }
      }
      Else
         Send %PriorKey%%Input%
   }
   ...
}

Re: Time threshold...

Posted: 10 Jul 2021, 08:20
by akirofe
just me wrote:
10 Jul 2021, 07:19
Maybe:

Code: Select all

HookEnded(InputHook) {
   ...
   If (EndReason = "Max") {
      If (IsDown) && ((A_TickCount - IsDown) >= Treshold) {
         Switch Input {
            Case "s":   ; a & s
               Send ...
            Case "d":   ; a & d
               Send
            Case "f":   ; a & f
               Send ...
            Case " ":   ; a & space
               Send ...
            Case "w":   ; a & w
               Send ...
            Case "e":   ; a & e
               Send ...
            Default:    ; a & anything else
               Send %PriorKey%%Input%
         }
      }
      Else
         Send %PriorKey%%Input%
   }
   ...
}
Thank you JustMe!!! I tried but got error on the "..." - I am not good enough without being spoon fed... :( My codes are below please help me a bit more?

Code: Select all

HookEnded(InputHook) {
   ...
   If (EndReason = "Max") {
      If (IsDown) && ((A_TickCount - IsDown) >= Treshold) {
         Switch Input {
            Case "s":   ; a & s
		send {WheelDown}{WheelDown}{WheelDown}
		return
            Case "d":   ; a & d
		send {WheelUp}{WheelUp}
		return
            Case "f":   ; a & f
               Send LButton
            Case " ":   ; a & space
               Send RButton
            Case "w":   ; a & w
               Send Escape
            Case "e":   ; a & e
               Send Delete
            Default:    ; a & anything else
               Send %PriorKey%%Input%
         }
      }
      Else
         Send %PriorKey%%Input%
   }
   ...
}
[Mod edit: [code][/code] tags added.]

Re: Time threshold...

Posted: 11 Jul 2021, 05:47
by boiler
I’m pretty sure the are just meant to represent the rest of the code that appeared there already. For the first one, it looks like it would be:

Code: Select all

   EndReason := InputHook.EndReason
   Input := InputHook.Input
   InputHook.Stop()
And for the last one, it would be:

Code: Select all

   IsDown := 0
   PriorKey := ""

Re: Time threshold...

Posted: 11 Jul 2021, 10:36
by akirofe
just me wrote:
10 Jul 2021, 07:19
Maybe:

Code: Select all

HookEnded(InputHook) {
   ...
   If (EndReason = "Max") {
      If (IsDown) && ((A_TickCount - IsDown) >= Treshold) {
         Switch Input {
            Case "s":   ; a & s
               Send ...
            Case "d":   ; a & d
               Send
            Case "f":   ; a & f
               Send ...
            Case " ":   ; a & space
               Send ...
            Case "w":   ; a & w
               Send ...
            Case "e":   ; a & e
               Send ...
            Default:    ; a & anything else
               Send %PriorKey%%Input%
         }
      }
      Else
         Send %PriorKey%%Input%
   }
   ...
}
Hi Justme,

With my very limited knowledge and with a lot of shooting in the dark, I have implemented your code into the below but I must have done something wrong :headwall: Could you please help me to fix? And, could you please help me a bit more: I couldn't find where it specifies "a" in your code ie. if I want to have another codes with, say, "f" instead of "a" for things like: f+a=Tab,... then where should I replace that "a" to an "f" in your code please?

Thank you very much Justme!!

Code: Select all

HookEnded(InputHook) {
   EndReason := InputHook.EndReason
   Input := InputHook.Input
   InputHook.Stop()
   If (EndReason = "Max") {
      If (IsDown) && ((A_TickCount - IsDown) >= Treshold) {
         Switch Input {
            Case "s":   ; a & s
               Send {WheelDown}{WheelDown}{WheelDown}
            Case "d":   ; a & d
               Send WheelUp}{WheelUp}{WheelUp}{WheelUp}
            Case "f":   ; a & f
               Send LButton
            Case " ":   ; a & space
               Send RButton
            Case "w":   ; a & w
               Send Escape
            Case "e":   ; a & e
               Send Delete
            Default:    ; a & anything else
               Send %PriorKey%%Input%
         }
      }
      Else
         Send %PriorKey%%Input%
   }
   IsDown := 0
   PriorKey := "a"
}

Re: Time threshold...

Posted: 11 Jul 2021, 11:18
by akirofe
boiler wrote:
11 Jul 2021, 05:47
I’m pretty sure the are just meant to represent the rest of the code that appeared there already. For the first one, it looks like it would be:

Code: Select all

   EndReason := InputHook.EndReason
   Input := InputHook.Input
   InputHook.Stop()
And for the last one, it would be:

Code: Select all

   IsDown := 0
   PriorKey := ""
Thank you very much Boiler!! (I still can't get it to work for another reason below, Thank you!)