#MaxHotkeysPerInterval error in AHK. If statement wrong? - autohotkey

I want my Vol. Up/Down to have multiple 'profiles' depending on a variable called 'startVar'.
But the code I wrote does not work.
Volume_Down::
if(startVar == 0 ){
SendInput {Volume_Up}
;SoundSet -5
return
}
else if (startVar == 1 ){
Send {Left}
return
}
return
Volume_Up::
if(startVar == 0 ){
SendInput {Volume_Down}
;SoundSet +5
;Sleep 30
return
}
else if (startVar == 1 ){
Send {Right}
return
}
return
I want the Vol.-Up/Down keys to either act like Left/Right or like usual.
But when I want them act like Vol.-Up/Down I get that error:
Error
I commented the function SoundSet although that worked because I want to have the Windows-Volume-GUI

You are receiving this message because the keyboard hook isn't used in your script to implement those hotkeys, which causes the Send command to trigger them over 70 times in a 2 second interval (default values for #MaxHotkeysPerInterval and #HotkeyInterval if you don't specify them in your script).
To avoid this problem, specify #UseHook somewhere above the definition of the hotkeys or prefix them with the dollar symbol $.

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.

autohotkeys using ifwinactive with expression not working

I am using AutoHotKeys to test if a window is active along with an expression. I don't seem to be able to get it to work. I am assigning the expression to a variable and then testing for ifWinActive and the variable. AutoHotKeys doesn't seem to be able to evaluate the expression correctly. This is my script:
^W::
;hotkey always fires
done = false
SetTimer, CheckPopups, 10000 ; check every 10 seconds for window
CheckPopups:
this := (done != true)
#IfWinActive "Volume Spike - Down" and this
{
;specific lines only when active window is true and done is false
msgbox hello
done := true
}
IfWinNotActive Volume Spike - Down
{
done = false
}
When I launch the script and the window is not active, it shows the message box Hello. Then 10 seconds later it shows it again. It should only show the message box if the window is active and done = false. Any idea what I am doing wrong?
You're using #IfWinActive, which is a directive used to create conditional hotkeys. You should use IfWinActive instead.
You can also use the function version, WinActive() inside your if-clause. It makes it look a little cleaner in my opinion.
Here's a short example:
#Persistent
done := false
SetTimer, CheckPopups, 1000 ; Check every second for window
return
CheckPopups:
if ( WinActive("Volume Spike - Down") ) and (!done) {
msgBox, Hello
done := true
} else {
done := false
}
return

Use of application name with space(s) with WinExist

So I wanted to check if certain application exists or not.
If it does and there was no input within 4.5 min, switch to that app and perform some task.
Basically an AFK cheater.
This is what I have so far:
#SingleInstance force
#Persistent
settimer, idleCheck, 1000; check every second
return
idleCheck:
if WinExist(App Name with Spaces); if app is running
{
if(A_TimeIdle >= 270000); and there was no input in 4.5 min
{
WinActivate; switch to that app
sendInput z; and perform an action
}
}
return
Now obviously that doesn't work since I'd not be posting here otherwise.
The question is very simple yet I couldn't find an answer.
Thanks in Advance.
WinExist is a function and function parameters are expressions...
In expressions you need to use double quotes " around strings and you don't need % around variables
you also need to have a space before the semicolon to use comments
#SingleInstance force
#Persistent
settimer, idleCheck, 1000 ; check every second
return
idleCheck:
if WinExist("App Name with or without Spaces") ; if app is running
{
if(A_TimeIdle >= 270000) ; and there was no input in 4.5 min
{
WinActivate ; switch to that app
sendInput z ; and perform an action
}
}
return
Hope it helps

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