autohotkeys using ifwinactive with expression not working - autohotkey

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

Related

Repeatedly calling a hotkey

I've tried to implement a t flip flop(I think this is what it's called) into my program but am having some issues with it. The idea is to have the program start and stop while using the same hotkey. This is what I have so far.
looping := false
pass = 0
max = 2
^r::
pass++
looping := true
while(looping = true AND pass < max)
{
Send, stack overflow, save me!
}
looping := false
pass = 0
return
When I run the program and hit the hotkey the while loop starts. However, when I attempt to break the loop by pressing ^r I get no response and the program keeps looping.
I think you are referring to a "toggle" script. I am not what sure you are trying to achieve exactly, but the key is using a logical not: looping := !true. More about it here.
looping := false
pass = 0
max = 2
^r::
pass++
looping := !true
while (looping & pass < max)
{
Send, stack overflow, save me!
}
pass = 0
return
There's a lot of resources for this, here are a few:
https://autohotkey.com/boards/viewtopic.php?t=11952
http://maul-esel.github.io/ahkbook/en/toggle-autofire.html
https://www.reddit.com/r/AutoHotkey/comments/6wqgbu/how_do_i_toggle_hold_down_a_key/dmad0xx

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

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

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.

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