I have a script which contains three variants like these for 50+ keys. I wonder, how could I shrink it?

; Press "a" = Option 1 (with 500 ms sleep)
; Press "Ctrl + a" = Option 2 (with 500 ms sleep)
; Press "Ctrl + Alt + a" = Option 1 (with 1000 ms sleep)

a::
    Send, {Enter}
        Sleep, 100
    Send, 1
        Sleep, 500
    Send, {Enter}
Return

^a::
    Send, {Enter}
        Sleep, 100
    Send, 2
        Sleep, 500
    Send, {Enter}
Return

^!a::
    Send, {Enter}
        Sleep, 100
    Send, 1
        Sleep, 1000
    Send, {Enter}
Return

This works how I want it to work. What's important is the option chosen (1 or 2) and the two different Sleep values for "Option 1". I'd like it to work just like this.

I tried using GetKeyState (even if the function is recommended, not this) without success. Two problems:

  1. I can't press the Ctrl or Alt before the "a" key, unlike in the original one. So I had to put a Sleep at the beginning and press the modifiers in the first second.
  2. It still didn't work though, because if I don't fill those variables with pressing the actual keys (Ctrl and/or Alt), it gives an error message.

I could find workaround for both, but I felt it just won't work after all. Here's the code:

a::
    Sleep, 1000
    GetKeyState, AltState, Alt
    GetKeyState, CtrlState, Ctrl
    Send, {Enter}
    if (CtrlState = D) {
        Send, Option 2
            Sleep, 500
    }
    else {
        Send, Option 1
        if (CtrlState = D and AltState = D) {
            Sleep, 1000
        }
        else {
            Sleep, 500
        }
    }
    Send, {Enter}
Return

After this failed I thought about using multiple KeyWait commands, but I'm not sure anymore.

TL;DR. If an experienced AHK user could help with a shorter, more efficient alternative or a solution for the GetKeyState variant (or debug it), that would be much appreciated!


Edit: Using the wildcard '*' and the GetKeyState as a function, the code works better, than the original and it contains less repetitions, making it easier for me to modify later, if needed.

*a::
    Send, {Enter}
    Sleep, 100
    if GetKeyState("Control", "P") and not GetKeyState("Alt", "P") {
        Send, 2
        }
    else {
        Send, 1
        }
    if GetKeyState("Alt", "P") and GetKeyState("Control", "P") {
        Sleep, 1000
        }
    else {
        Sleep, 500
        }
    Send, {Enter}
Return
up vote 1 down vote accepted

I'm unclear on what problem you're actually trying to solve. You are just trying to combine the first script into more efficient code? Or does the first script not work in some way you would like it to?

You can use a star modifier ('*') in front of the hotkey to allow it to trigger with modifiers already pressed (and then you will have to handle those appropriately if they are there are not there, which your example code partially does). I believe this addresses the first item you listed as an issue.

i.e.,

*a::

This will trigger on a, #a, +a, ^a, !a, ^!a, etc.

You can also call GetKeyState() without assigning intermediate state variables and check for the modifiers being pressed.

If GetKeyState("Control", "P") && GetKeyState("Alt", "P") {
}
  • The first code I pasted works perfectly. I don't have a problem with it, more like it would be a preference, to have the three hotkeys merged into one. About your answer, the wildcard actually could solve my problems, I didn't know about that. And with the merging part, I'm thinking about subroutines now, but first I'll try the GetKeyState way again, using the function this time. – deviance Aug 20 at 5:19

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.