Store key modifier as variable - autohotkey

Is there way to use variable for key modifier, for example:
var = +
%var%c:: do something ; Equal to Shift-C
... Well, StackOverflow trying to force me to write something more about the task. But I'm really don't know what to add to what have been already said. Also I've already read AHK forums, but can't find answer there.

Dynamic hotkeys are defined using the Hotkey command.
From the AHK website on hotkeys: https://autohotkey.com/docs/Hotkeys.htm
By means of the Hotkey command, hotkeys can be created dynamically
while the script is running. The Hotkey command can also modify,
disable, or enable the script's existing hotkeys individually.
This faq page on dynamic variables provides something close to what you are asking for:
https://autohotkey.com/board/topic/97097-faq-variables-dynamic-variables-literal-strings-and-stuff-like-that/
keys = abcdefghijklmnopqrstuvwxyz
StringSplit, keys, keys
Loop, %keys0%
Hotkey, % keys%A_Index%, keydown
return
keydown:
ToolTip, %A_ThisHotkey% was pressed
I've verified that the following works as expected:
var = +c
Hotkey, %var%, keydown
return
keydown:
ToolTip, %A_ThisHotkey% was pressed

Related

71 hotkeys have been received in the last X ms

I have a script that assign F1 for a global task:
f1::Run D:\Download
A program needs to use that key, so I put this:
#IfWinActive, ahk_exe inkscape.exe
F1::send {f1}
return
However when I press it, this error hits:
If yes, nothing happens. If no, the script exits.
Do you know what happens?
The problem is that your hotkey keeps triggering itself over and over a again in a loop. The $ modifier will fix it. That way the hotkey wont get triggered when the source of the key press is a Send command.
However, you don't actually need this at all.
You should use the #IfWinNotActive directive.
#IfWinNotActive, ahk_exe inkscape.exe
F1::Run, D:\Download
#IfWinNotActive
Alternatively, you could just not create a context sensitive hotkey, and use the ~ modifier. That way the hotkey will always retain its normal functionality when you press it.
~F1::Run, D:\Download

AutoHotKey function to perform File-Rename without relying on sending F2 key code

I want define a custom hotkey to rename a selected file in File Explorer. So my new hotkey should behave exactly like the F2 key does by default. That is, when I press the hotkeys, the file name should be editable, allowing me to type a new name. However, I can't use the F2 key to cause windows to do this.
The reason is that I'm using the default hotkeys for something else. I am often running an application (unrelated to AutoHotKey) where the buttons in the UI are triggered using keyhooking for all of the F keys. The only suggestions that I can find on this are to have my custom hotkey use 'send' to raise the default key codes that would be associated with the action. This won't work, because I am using those hotkeys for something else. What I need is a solution that causes a file to be renameable without sending the F2 keycode.
^+!R::
Send {F2} ;This won't work for me
return
Actually the original hotkey can be used, just add $ before the hotkey that you don't want to be fired by the send command. Also using app-specific hotkeys a good idea to minimize possible conflicts.
Try this:
#If winActive("ahk_exe Explorer.EXE")
^+!R::
send {F2}
return
$F2::
send {down}
return
In case you have an application which scans the F2 key globally and unconditionally, and you cannot redefine it, there is not much you can do from within AHK. So ideally you should get rid of that application, and use e.g. AHK for same functionality, or find some workaround.
In this particular case the easiest workaround is alternative way to rename the file:
^+!R::
send {AppsKey}
sleep 100
send {m}
return

AHK script designed to toggle based on CapsLock Status always toggles on 'off' and I cannot change it to 'on'

(Note: Very new to scripting, borrowed some phrases from other scripts I've online.) I have Carpal Tunnel and play a video game that does not have any key-bind options not set to the F1-F0 keys so I want to rebind the F1-F4 keys to Z-V but only when capslock is enabled, to prevent being unable to type in chat windows and in other programs without closing the script. However, the script re-binds the basic keys to the f-keys ONLY when capslock is OFF, rather than allowing me to change it to ON. Not sure why.
I've tried 'hotfixing' it by rebinding it to Numlock, but when I moved to CapsLock changing 'OFF' to 'ON' did not keep the script from only rebinding the keys while CapsLock was OFF. Not sure why.
$Z::
GetKeyState, state, NumLock, T
if state = D ; NumLock is toggled ON
send, {z}
else
send, {F1}
Return
$X::
GetKeyState, state, NumLock, T
if state = D ; NumLock is toggled ON
send, {x}
else
send, {F2}
Return
etc...
etc...
I expected changing the value 'OFF' to 'ON' would result in the key rebinds only happening during the CapsLock status being toggled on.
Have you checked if you restarted the script after making changes? It's a very common mistake, not only among beginners. According to your example, your keys Z..V should behave as F1..F4 only when the NumLock is toggled off.
Given the nature of your script, you can consider to add the directive #SingleInstance Force which will automatically replace any older instance of your script by a new one each time you run the script again, making testing easier.
You can do conditional binding much easily with an #if directive, which makes the subsequent hotkeys and hotstring only effective when a condition is met.
To check the state of the CapsLock or NumLock keys you can also use the built-in function GetKeyState, which for toggle keys, such as CapsLock or NumLock, with the "T" mode returns either True or False based on the toggle state of the key.
Also, if you want to remap keys, you can simply write the target key's name at the right of the hotkey, which will completely bind the keys, on both Down and Up events. However, for this to work, you must specify your triggering keys as lowercase, since specifying uppercase would only trigger the remap when pressed the keys with the Shift key as well (the CapsLock would have no effect), and that is not your desired behaviour. [More on remapping keys]
Here is an example of what you could do:
#If GetKeyState("CapsLock", "T")
z::F1
x::F2
c::F3
v::F4
Note that, since key remapping always uses the keyboard hook (because it needs to register the Up events as well), there is no need to use the $ prefix in your hotkeys at all.
Nonetheless, you can automate your script even more if you use as condition for your hotkeys the currently active window and bind them to your game using the #IfWinActive directive.
However if there are also chats in the game, you might want to combine both conditions in a single #If, using the built-in function WinActive like this:
#If GetKeyState("CapsLock", "T") and WinActive("My Game Title")
z::F1
; ...
You can check how to narrow your search for the window by its title on the documentation for the WinTitle parameter.
If you want to improve your script even further, you could explore if there is any detectable change on the game window when the chat is active, such as if a certain control exists (you can check that as if it was another window using the WinExist function to check for a certain Window class.
To seek for such changes, you can use a script as the following (from the MouseGetPos documentation):
#Persistent
SetTimer, WatchCursor, 100
return
WatchCursor:
MouseGetPos, , , id, control
WinGetTitle, title, ahk_id %id%
WinGetClass, class, ahk_id %id%
ToolTip, ahk_id %id%`nahk_class %class%`n%title%`nControl: %control%
return
Which would allow you to see the window information of the windows below your mouse. You can use it to check for the name or class of the chat control by placing your mouse over it.
However, keep in mind that many games do not use Windows controls at all in their interfaces and rather just draw them on screen by themselves, so if you're trying this and can't progress much after a while you shouldn't waste too much time on it and rather enjoy playing with your CapsLock toggled binding.
Another tricky way to check if the chat is active is searching for an image on the screen or a pixel color using ImageSearch or much simpler PixelGetColor, but you can only do that if your game's interface is not very complex/animated.

vscode: Is it possible to make (not remap) `caps lock` as one of the modifier keys?

I am not asking to remap Caps Lock to other modifier keys but I want to configure Caps Lock as one of modifier key for my own usage. Any ideas? :D
On Windows you can use AutoHotKey(usually briefly as ahk) with the WinActive function to make the ahk script only work when you're in vscode, mapping CapsLock+* keys to usually-not-used combinations like ctrl+shift+alt+* and write the ctrl+shift+alt+* keys to vscode's key configs.
It would roughly look like this:
; comment: the class used here is made up
; right click a running script in the system tray and go to "window spy" to get the right class name
; there are also usual `if`s but this one applies the condition to all the code following it
#If WinActive("ahk_class VSCode")
CapsLock & a::
SendInput, ^+!a
return
And of course if you want to get the function of capslock in the editor, you can easily use a combination like CapsLock & Shift to acomplish it like above.
For x11 OSes like most Linux distros, use xmodmap. Something like
keycode 66 = Alt_L Meta_L
clear mod1
add mod1 = Alt_L Meta_L
in your .Xmodmap file should suffice.
Then run:
xmodmap .Xmodmap

How to remap key in certain case and not remap in other case with autohotkey?

I want to remap alt+e when caps is on in autocad.
And when capslock is not on, alt+e should open menu edit.
I use script like this
<!e::
if(GetKeyState( "CAPSLOCK", "T" ))
{
SendInput erase{space}wp{space}
}
else
{
Send !e
}
When I turn on capslock, remap key is OK.
When I turn off capslockand alt+e, menu edit opened, but closed immediately.
Thanks.
You will want a $ at the beginning of your hotkey to prevent the endless loop that the !e in your else block will trigger. You will also want to add a Return at the end of the hotkey to prevent the script from continuing into what is below this hotkey.
$!e::
if GetKeyState( "CapsLock", "T" )
Sendinput, erase{space}wp{space}
else
Sendinput, !e
Return
(Brackets are only required when if/else blocks are more than one line.)
Beyond that, the likely issue is that it's an alt hotkey that is also set to send alt.
I say this is an issue because if you press and hold alt, it activates menus,
and then the script sends alt, which will be in conflict with that.
As Ricardo said, the ideal way to script this is with the #IF command (only included with AHK_L).
#If GetKeyState("CapsLock", "T") and WinActive("AutoCAD")
!e:: SendInput, erase{space}wp{space}
#If
Notice that you can add the WinActive() function to the #If command's expression.
Try it without that first, and also realize that the application's title needs to be exactly "AutoCAD" at all times for that to work. I would recommend finding AutoCad's ahk_class,
with AHK's window spy, instead of using the title.
If it still does not work, it is likely that AHK is sending faster than AutoCAD would like to receive.
Info on how to deal with that can be found here.
Try to change your else block to this:
Send, {ALTDOWN}e{ALTUP}
I do not rely on these symbols to send keystrokes in AutoHotKey.