AutoHotKey redefining Shift key effective for first key press only - autohotkey

Here is a short AHK script which does two things:
Creates an extra Shift key on right alt (AltGr)
Redefines CapsLock as a function key, to be used to type extra characters.
#InputLevel 1
RAlt::RShift ; define shift on right-alt
SC03a::F20 ; define special function key on capslock
#InputLevel 0
F20 & SC002:: ; the '1' key
GetKeyState, sh, Shift
if sh = D
Send ¡ ; upside-down exclamation
else
Send ¹ ; superscript 1
return
It nearly works:
pressing AltGr plus 1 produces '!', as you would expect for a shifted key.
pressing CapsLock plus 1 produces '¹', as you would expect given the definition above.
The problem arises when you hold down both AltGr and CapsLock and press '1'. This produces '¡' as expected for the first character, but subsequent presses produce '¹'. It appears the Shift state gets magically cancelled after the first press.
Note, this doesn't happen with a "real" Shift key - Caps+Shift+1 produces '¡' every time, so it appears to be a problem with redefining another key to be Shift, where its shift state is cancelled after the first instance.
Am I missing something?

A while loop might be what you're looking for.
Example:
LShift::
while (GetKeyState("LShift", "P"))
{
SendInput, {¡}
Sleep, 100
}
return

Related

Remap keys in loops

Background: I'm trying to have a f-mode and d-mode which means if I press down the f key and press another key like i then nothing happens excepts a shortcut. let say it will send Up key instead of f and I.
Issue: how I can remap a pressed key (I in my example) to a shortcut (Up as example)?
Code:
d::
f::{
;...
loop{
if !GetKeyState("f","p") && !GetKeyState("d","p"){
break
}
if GetKeyState("i","p") {
OutputDebug "i"
send "{up}"
continue
}
; ...
}
}
Looks like you want to make a custom combination.
From the Docs:
You can define a custom combination of two keys (except joystick
buttons) by using " & " between them. In the below example, you would
hold down Numpad0 then press the second key to trigger the hotkey:
Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
Numpad0 & Numpad2::Run Notepad
But also note:
The prefix key loses its native function: In the above example,
Numpad0 becomes a prefix key; but this also causes Numpad0 to lose its
original/native function when it is pressed by itself. To avoid this,
a script may configure Numpad0 to perform a new action such as one of
the following:
Numpad0::WinMaximize A ; Maximize the active/foreground window.
Numpad0::Send {Numpad0} ; Make the release of Numpad0 produce a Numpad0 keystroke. See comment below.
This is to prevent holding down a key from spamming inputs while you wait to press the second part of a key combination. So essentially, your 'f' and 'd' keys will now perform their normal functions when you release them instead of initially pressing them down.
Anyways, the code would become:
f & i::
d & i::
Send {Up}
return
f::f
d::d

Using GetKeyState for triple key combinations does not work

In the following script,when I press the CapsLock and Alt keys and then the J key,"is work" message will not pop up. Only by simultaneously pressing the CapsLock, Alt, and J keys and immediately releasing the keys will "it work" message pop up.
CapsLock & J::
if GetKeyState("Alt","p"){
MsgBox is work
}
return
Change the key J to K, as follows:
CapsLock & K::
if GetKeyState("Alt","p"){
MsgBox is work
}
return
This allows you to press the CapsLock and Alt keys first and then the K key to pop up the "it work" message. I tried other keys, such as A, S, D, F, H, and so on.But you can't change it to G. Only three keys can be pressed at the same time and immediately release the normal output "is work"
I don't understand why?
When custom key combinations use GetKeyState, what is the order in which the keys are executed?
As soon as you trigger your hotkey by pressing CapsLock + J or K it's looking to see if Alt is pressed. So if there is any delay between when the hotkey is triggered and Alt is pressed, then your MsgBox won't show.
To get it to work every time, start by holding the key that GetKeyState is looking for (Alt) and then hold your other keys in order from left to right as listed. So, hold Alt, then hold CapsLock, then press J or K.

Avoiding loop when Double pressing same shortcut key without changing original 1 press shortcut key function (Autohotkey)

I want to produce something like this :
1. When i press Esc 2 times (double) i want to produce my "made-up custom action"
2. When i press Esc 1 time i want to produce the original Escape
ok, here is the explanation of my question :
This code should apply as global, means when i start the script it will work on all windows
%ALAT1% is variable the Active Windows title , abbreviation "Anime Land Akui Transform" some kind of silly anime game
If i press Esc one time . it will "pause" the game, but when i press Esc 2 times, it will "exit" the game"
I want to do a custom action when i press Esc 2 times, but i also don't want the original Esc key function got override when i press 1 time.
Escape::
if (A_PriorHotkey = A_ThisHotKey and A_TimeSincePriorHotkey < 400)
WinActivate, %ALAT1%
IfWinActive, ahk_class TscShellContainerClass
{
Send {F5} ; F5 contains another action
}.
else
{
*Do original function of Escape i.e Send {Escape} ; Now this is the problem
}
return
after i try the code above : suppose i press "Escape" button it will loop the Escape as if i press Escape 2 times. So my real question is how to make "original 1 times press Esc key function" won't loop to "our custom 2 times press Esc key function" ?
Change the first line of your code to;
$Escape::
This will set it so that the hotkey is only triggered by real keystrokes not simulated ones.

Remapping alphabet or number key pairs to perform alt,ctrl,shift functions

I work with a hospital data entry system where no customization is allowed. I have found AutoHotKey to provide effective ways to work around the this system's "slow clunkiness".
What I need are more function keys on the keyboard. The best way I have found to approximate that is by remapping key pairs 1 Q:: Alt n, 2 w::ctrl r....ect. The best I could come up with was from AHK site's example and explanation of how to remap letter keys to other letter key destination. I tweaked and adjusted and came up with the following:
1 & q::
SetKeyDelay -1, 40 ;
Send {ctrl Down} ;
Send {Blind}{f Downtemp}
return
1 & q up::
SetKeyDelay -1 ;
Send {Blind}{ctrl up}
Send {Blind}{f Up}
return
This code will do the job but it has a downside. The first key in the sequence looses it's regular function. In this case, I've lost the use of my top row of numbers to become function keys. Is it possible to have the first key revert back to it's native function automatically after it was used in the key pair? I and the other pharmacy personnel will be most grateful for any help you can provide. Thank You.
Key combinations with & produce prefix keys. To restore a prefix key's original function, you need to define it explicitely:
1 & q::Msgbox, 1
1::Send, 1
+1::Send, {!} ; SHIFT + 1 may depend on your keyboard layout
However, it makes sense to arrange your key combinations in a way that produces as few prefix keys as possible. In your example, if you want to define hotkeys like 1 + q, 2 + q, 3 + q, and so on, it may be smarter to use q as the first key, leaving you with the necessity of redefining only one key:
SendMode, Input
q & 1::Msgbox, 1
q & 2::Msgbox, 2
q & 3::Msgbox, 3
q::Send, q
+q::Send, Q
; AltGr+q and CTRL+ALT+q also do something in Germany ;)
<^>!q::Send, #
^!q::Send, #
As you can see in the example, you always have to look out for keys that have a (usually third) functionality that's triggered by AltGr or CTRL+ALT. But this strongly depends on your keyboard layout.

Eval / RegExp listen with Autohotkey

I think this must be possible but I can't find it in the documentation anywhere on autohotkey
I want to do something like:
[a-z0-9]::
SoundPlay, %A_WinDir%\Media\[\1].wav
SoundPlay *-1
i.e. listen for all keys a to z and 0-9 find the relevant wav file (a.wav etc..) and play it. If it can't be found Play a default sound.
Is this way out of AHK's league? Should I stick to doing this in python??!
Many thanks in advance
You can use the Hotkey Command to assign all possible hotkeys to the label.
The first loop here uses a trick with converting values to their ASCII codes, doing math, and converting them back to characters. The logic works like, "What is the 5th character after 'a'?" -- to which it replies 'f'.
#Persistent
Loop, 26
Hotkey, % Chr(Asc("a") + A_Index - 1), MyLabel
Loop, 10
Hotkey, % A_Index - 1, MyLabel
return
MyLabel:
MsgBox You pressed %A_ThisHotkey%
return
I'm not aware of a way to use a regex to specify the hotkey, but this is how I've done it in one of my scripts:
#::
a::
b::
c::
; (all other alpha keys...)
; Pass key on, if not in subscription list
If(in_edit_screen())
{
; Handle caps lock
If(GetKeyState("Capslock", "T"))
{
; Send uppercase letter
StringUpper key, A_ThisHotkey
Send %key%
}
Else
{
Send %A_ThisHotkey%
}
Return
}
; etc.
Return
This is part of a routine that's called whenever a certain window is focused, but the window in question has a few different modes; in one of those modes (indicated by the in_edit_screen flag), I want to just pass the keys through, while in another mode, I want the keys to do something special. A_ThisHotkey is the variable that tells the routine which key/key combination the user actually pressed.
Why not launch a script where you use:
Input, CI_KeyVar, I L1
and then read-out which key was pressed (variable = CI_KeyVar), do your thing (check if the ascii code falls between 0 and Z because this input will act on any input) and re-launch the script to wait for the next key press....
The way out would be to trigger on e.g. the esc key, so the script stops.