Reputation: 3
I've found AHK codes that separately work "ok" but I need one inside another. So, I have:
1. The first rapidly fires click when you hold down the left mouse button:
~$LButton::
While GetKeyState("LButton", "P"){
Click
Sleep .1 ; milliseconds
}
return
2. The second is a toggle script that sends the same left mouse button firing events but can be toggled on and off with a button press (F8 in this case)
toggle = 0
#MaxThreadsPerHotkey 2
F8::
Toggle := !Toggle
While Toggle{
Click
sleep 1
}
return
What I need is: when I push F8 once, I want my left mouse button to fire click events rapidly while holding it. When I push F8 again it should do nothing. If it's important, I need those clicks while holding Ctrl in-game. I've read a bit about AHK and tried this code but it doesn't work any close to what I want:
toggle = 0
#MaxThreadsPerHotkey 2
F8::
Toggle := !Toggle
If Toggle{
~$LButton::
While GetKeyState("LButton", "P"){
Click
Sleep .5 ; milliseconds
}
}
return
This one gives me errors about missing "return" but I tried a lot of merging variations.
Also, I've read a lot about MaxThreads and still don't know why there should be 2 and what is it for.
Upvotes: 0
Views: 6026
Reputation: 6489
Firstly, not sure what amount of time you're trying to give the Sleep
commands, but decimal numbers wont work. Just whole numbers, and they're in milliseconds. .1
and .5
are likely interpreted as 0
, not sure though. Also, the sleep command isn't as accurate as you may think it is. Read the remarks section in the documentation for more.
Secondly, you shouldn't loop inside hotkey labels. It's bad practice due to AHK not offering true multithreading.
Though, at the end of the day, it wont make any difference if this is all your script it.
For future reference if you want to start writing nicer and bigger scripts, I'll show you the usage of timers though. They should be used for this.
LButton::SetTimer, MyCoolFunction, 0 ;when LButton is clicked down start a timer with the shortest possible period
LButton Up::SetTimer, MyCoolFunction, Off ;when LButton is released, stop the timer
MyCoolFunction()
{
Click
}
And same for your toggle version, you don't want to loop inside a hotkey label:
F8::
toggle := !toggle
if(toggle) ;if true
SetTimer, MyCoolFunction, 0
else
SetTimer, MyCoolFunction, Off
return
MyCoolFunction()
{
Click
}
And if you don't know what toggle := !toggle
actually is, and want to know, you can read a previous answer of mine here. It also shows how you can compact that code down to just one line of code. And also explains why there's no need to define the variable toggle
on top of your script (as you were doing).
And about #MaxThreadsPerHotkey
2
:
It's because AHK doesn't offer true multithreading. When you're looping side a hotkey definition, that hotkey is completely locked up. You can't run the hotkey again to stop the loop. Unless, you set the hotkey to use more threads (better to call them instances) than one.
That way you're able to launch the hotkey again and you're able to change the toggle
variable's value so you can stop the loop.
But again, you shouldn't loop inside hotkeys. If you use a timer, like I showed above, you don't need to worry about this dirty workaround.
And then to the new code you want to create.
Well first about what went wrong in your attempt. I guess it was a good thought, but it's not even close. Hard to say what exactly is wrong in it, since it's not even close to working. I guess what I can say is that hotkey labels (hotkey::
) are evaluated once when the script starts, and then never again. So you can't put them inside some runtime logic. The Hotkey
command would be used for that.
Luckily your problem is actually much simple than that. You don't need to mess around with the Hotkey
command.
All you're looking to do is toggle the hotkeys on/off. Suspend
is used for that like so:
F8::Suspend
And now the script's hotkeys (and hotstrings) toggle on/off every time you press F8.
So here's your final script:
LButton::SetTimer, MyCoolFunction, 0 ;when LButton is clicked down start a timer with the shortest possible period
LButton Up::SetTimer, MyCoolFunction, Off ;when LButton is released, stop the timer
MyCoolFunction()
{
Click
}
F8::
Suspend
SetTimer, MyCoolFunction, Off ;set the timer off just incase we hadn't released LButton before we hit F8
return
Upvotes: 1