What was required was a script that would spam the keys you were holding, with some conditions.
For example:
if you hold 1, it spams 1.
If you then hold a modifier without releasing 1, it spams <modifier>+1
if you release the modifier, it goes back to spamming 1.
He also wanted conditions, eg:
If I am holding Ctrl, and hit Q, I only want it to send Ctrl+Q once.
Releasing Q and re-hitting should allow another send of Ctrl+Q
How the code works:
At the start of the script is an array which configures the keys it watches for
key_list := ["1", "2", "3", "4", "5", "F1", "F2", "F3", "F4", "F5", "q", "g"]
Keys not in this list will not be spammed.
it then builds an "Associative Array" called keys, with one entry for each key, which is set to 0
so keys["q"] starts off as 0
It then declares some hotkeys for down and up events of each key, such that when a key is held, keys[<keyname>] is 1.
ie when Q is held, keys["q"] is 1, otherwise it is 0.
An endless loop is then kicked off, which constantly runs.
The endless loop cycles through all the keys like so: for key, value in keys
If keys[<key>] is 1, then that key is held.
A similar "Lookup array" is also present for the modifier keys, such that if CTRL is held, modifiers.Ctrl is 1. In this way, the code is able to build a list of modifiers for the send command - ie if modifiers.Ctrl is 1, but the rest are 0, the modifier string will be built as "^"
The "exceptions" system works thus:
If you wish to stop a key repeating, set keys_modifiers[<keyname>] to 1.
So to stop Ctrl+Q from repeating, if the code detects Q is hit with CTRL held, it sets keys_modifiers["q"] to 1
The keys_modifiers value for each key is set to 0 when that key is released.
Code: Select all
; To add a new key to the script, add it to this array:
key_list := ["1", "2", "3", "4", "5", "F1", "F2", "F3", "F4", "F5", "q", "g"]
; Init lookup array for modifiers
modifiers := {LAlt: 0, LShift: 0, LCtrl: 0}
; Build lookup array, declare hotkeys
keys := {}
keys_modded := {}
Loop % key_list.MaxIndex(){
key := key_list[A_Index]
; init array values
keys[key] := 0
keys_modded[key] := 0
; Declare hotkeys for up and down events
hotkey, $*%key%, keydown
hotkey, $*%key% up, keyup
}
Loop {
; Endless loop - always running
for key, value in keys {
; Loop through each of the keys
if (value){
; If the key is held...
; Detect if any modifiers held
if (modifiers.LAlt || modifiers.LCtrl || modifiers.LShift){
modifier_held := 1
} else {
modifier_held := 0
}
if (key = "q" && modifiers.LCtrl){
; Special case - CTRL + Q
if (keys_modded[key]){
; We already sent a modded version of this key, then ignore
; keys_modded[key] will be set to 0 on up event of key
continue
} else {
; We are going to send a modded version of this key, set keys_modded[key] to 1, so it ignores next time
keys_modded[key] := 1
}
}
if (key = "g" && modifier_held){
; Special case - ANY modifier and g
if (keys_modded[key]){
continue
} else {
keys_modded[key] := 1
}
}
; Build the list of modifiers to use for the send
s := ""
if (modifiers.LAlt){
s .= "!"
}
if (modifiers.LShift){
s .= "+"
}
if (modifiers.LCtrl){
s .= "^"
}
; Send the key with the modifiers
Send % s "{" key "}"
}
}
Sleep 20
}
; Any of the "keys" (ie not modifiers) being pressed will call this
keydown:
key := SubStr(A_ThisHotkey,3)
keys[key] := 1
return
; Any of the "keys" being released will call this
keyup:
key := SubStr(A_ThisHotkey,3)
; Remove " up" from end
key := substr(key, 1, StrLen(key) - 3)
keys[key] := 0
keys_modded[key] := 0
return
; Modifiers
$*LAlt::
$*LShift::
$*LCtrl::
mod := substr(A_ThisHotkey, 3)
modifiers[mod] := 1
return
$*LAlt up::
$*LCtrl up::
$*LShift up::
mod := substr(A_ThisHotkey, 3)
; Remove " up" from end
mod := substr(mod, 1, StrLen(mod) - 3)
modifiers[mod] := 0
return
; Quit script on Escape
Esc::
ExitApp