How to send an addition sequence after a series of input? - autohotkey

I want every time the series Ctrl GUpEnter and Ctrl GDownEnter are pressed, it will Send !wi afterward. Normal hotkeys work:
~^PgUp::
~^PgDn::Send !wi
But this doesn't work, although ~^g down enter isn't an invalid hotkey:
~^PgUp::
~^PgDn::
::~^g down enter::
::~^g up enter::Send !wi
Also, since I don't know many times Up and Down will be pressed before Enter, is there a way to make it skips the middle keys?

Try:
~^PgUp::
~^PgDn::Send !wi
~^g::
Input, key, V L1, {Enter}
if (ErrorLevel == "EndKey:Enter")
Send {Enter}!wi
return

A simple solution is to set a boolean flag when ^g is pressed. Then check this flag when enter is pressed and fire !wi if it is set. This however require that the flag is reset - so if some other key can end the sequence, it must be also reset by those keys (see bottom section of code for examples).
await := 0
~^g::
await := 1 ; set flag
tooltip %await%
return
~enter::
if (await = 1) {
await := 0 ; reset flag
sleep 300 ; safety pause
send !wi
tooltip %await%
}
return
; note: the 'await' flag must be reset if other
; key can end the sequence.
; here for example escape or mouse click
~esc::
await := 0
tooltip %await%
return
~lbutton::
await := 0
tooltip %await%
return

Related

How to press and hold 3 keys one after the other

New to Auto Hotkey. I’m looking to create a hotkey to press and hold Control, then press and hold Alt, then press “W”, then let go of all 3 and do the same after 30 seconds.
I tried this but unsure if it’s right. Thanks!
#SingleInstance, force
#MaxThreadsPerHotkey 2
F10::
Toggle := !Toggle
while Toggle
{
Send, {Ctrl}
Send, {Alt}
Send, {W}
Sleep, 30000 ;
}
Return
This should work:
#SingleInstance, force
F10::
Toggle := !Toggle
if (Toggle)
{
gosub, sub
SetTimer sub, 30000
}
else{
SetTimer sub, Off
}
Return
sub:
Send ^!w
return
Notes:
When a sleep command is used, the program is unable to detect hotkeys being pressed. Instead of using multiple threads, it would be better to implement a SetTimer/ Subroutine system.
In order to send Ctrl+Alt+W, just use Send ^!w. (^ means Control, ! means Alt, and and w means w; for more info, see modifiers.

Toggle infinite loop by the same key

I want to be able to press key and run an infinite loop, and be able to press the same key to stop the loop. In a simple case I want the script to click indefinitely:
XButton2::
if (Doing = 0)
{
Doing := 1
While Doing = 1
{
Click
}
return
} else {
Doing := 0
}
Unfortunately this doesn't work - XButton2 does not respond any more because it is running a script. I can switch Doing := 0 by other key but I want for it to be the same XButton2. Any simple way of doing this? I would avoid complicated solutions.
Use a timed subroutine. That's how you'd start/stop a loop in ahk usually.
For example:
clicking := false
label_click:
click
return
XButton2::
clicking := !clicking
if(clicking)
setTimer, label_click, 1 ; click once every millisecond (approx.)
else
setTimer, label_click, off
return
That is how I usually do it, though I'd love to see a more compact version.

Start & stop a script a looped action with a button

The script should to the following:
Press 'C': Start/Stop script
Left Mouse Button: Start/Stop the loop
Inside the loop: While holding down the Left Mouse Button, the left mouse button is repeated till I lift my finger of it.
The mouse goes back to the center of the screen after every click.
Alternative the mouse is moved X pixel down after each click and my script is very slow.
It goes click .. click .. click instead of ClickClickClick :(.
I changed it to this now, but the Left Mouse Button is always activated even when not holding it down, I can't stop/start the script with C too.
HotKey, ~$*LButton, myLButtonAction ; Activate the hotkey by default
return
~c:: ; configure a Hotkey: c will enable / disable your LButton actions
HotKey, ~$*LButton, toggle ; ON / OFF
return
myLButtonAction: ;cnote: this is NOT a hotkey, it's a label
Loop
{
Click
Sleep 7,516 ;your loop actions (see question code)
}
return ; don't forget your returns at the end of a label / hotkey
Looks like you need to use the Hotkey command.
x := (A_ScreenWidth // 2)
y := (A_ScreenHeight // 2)
HotKey, ~$*LButton, myLButtonAction ; Activate the hotkey by default
setMouseDelay, 0
setKeyDelay, 0
return
~c:: ; configure a Hotkey: c will enable / disable your LButton actions
HotKey, ~$*LButton, toggle ; ON / OFF
return
myLButtonAction: ; note: this is NOT a hotkey, it's a label
Loop ;loop the script until broken
{ ;loop start
GetKeyState, var, LButton, P ;Get the state of Lbutton
If var = U ;has it been released?
Break ;its been released so break the loop
;Send {LButton} ;It hasnt been released so send another Click
Click %x%, %y%
Sleep 100 ;time between presses, after sleep return to the top of the loop
} ;loop end
return ; don't forget your returns at the end of a label / hotkey
my script is very slow. It goes click .. click .. click instead of ClickClickClick :(
Include setMouseDelay, 0 into your auto-execution section. I already did this in the code example above.

Autohotkey continuous macro

since I have to give away my macro keyboard I found autohotkey to be reliable. Sadly I didn't really find out how to make continuous macros..
what I mean is: (pseudo code)
^!c::
while ^!c is not pressed again -> send keystrokes c
spamm infinite c keystrokes until I press the combination above again
How do I approach this?
toggle = 0 ; timer is off because toggle isn't yet initialized
return
^!c:: ; toggle timer
if toggle := !toggle
SetTimer, Send_c, 0
else
SetTimer, Send_c, off
return
Send_c:
Send c
Sleep, 300
return

Using GetKeyState() and loops

I'm trying to write a script that has a loop in which the upper arrow key is pressed every two seconds. The loop must be activated when I press the spacebar and deactivated when I press it again. I'm now using this.
$Space::
if GetKeyState("Space", "P")
{
Loop
{
Sleep 2000
Send {Up}
if GetKeyState("Space", "P")
{
return
}
}
}
For some reason, the if condition inside the loop doesn't work, i.e. I can't get out of the loop. I hope anyone can help me out...
You wouldn't need the first if GetKeyState("Space", "P")
and you would need to be holding space when the loop got to the second one
for it to break; and you would need to replace the return with break.
However I agree with Gary, although I would write it like this:
; (on:=!on) reverses the value of variable 'on'
; the first press of space reverses on's value (nothing) to something (1)
; the second press reverses on's value from (1) to (0)
; when (on = 1) delay will be set to 2000, and Off when (on = 0)
space::SetTimer, Action, % (on:=!on) ? ("2000") : ("Off")
Action:
Send, {up}
Return
% starts an expression.
From http://l.autohotkey.net/docs/Variables.htm
?:
Ternary operator
This operator is a shorthand replacement for the if-else statement.
It evaluates the condition on its left side to determine
which of its two branches will become the final result.
For example, var := x>y ? 2 : 3 stores 2 in Var if x is greater than y; otherwise it stores 3.
How about using SetTimer?
; Create timer.
SetTimer, SendUp, 2000
; Set timer to 'Off' at start of script.
SetTimer, SendUp, Off
TimerEnabled := False
; When Space is pressed toggle the state of the timer.
$Space::
If TimerEnabled
{
SetTimer, SendUp, Off
TimerEnabled := False
}
Else
{
SetTimer, SendUp, On
TimerEnabled := True
}
; Label called by timer to send {Up} key.
SendUp:
Send, {Up}
return