How to remap key in certain case and not remap in other case with autohotkey? - 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.

Related

How can I use autohotkey to stop WASD movement while holding down the left mouse button?

I'm interested in disabling the w,a,s, & d keys while holding down the left mouse button.
(Games such as cs:go and valorant penalize shooting while moving, so I'd like to preclude that situation entirely).
I just learned about autohotkey, so I'm sorry if I offend someone with this attempt at code(which obviously doesn't work):
while (GetKeyState("LButton", "P"))
{
w::return
a::return
s::return
d::return
}
Thanks, much appreciated!
I just want to add in the solution that #Spyre hinted at. The script does indeed become much smaller when you use the #If directive, and when the if statement fails, the hotkey doesn't fire, so it doesn't add to your overall hotkeys per interval. Here is my version of the script:
#If GetKeyState("LButton", "P")
w::
a::
s::
d::
Return
Use #If (docs):
#If, GetKeyState("LButton")
w::
a::
s::
d::return
#If
And if #If were to cause you trouble (like warned about in the documentation) (it's not going to happen if your script is this small and simple), you'd want to do turn on and off the hotkeys with the Hotkey command.
For example:
~LButton::ConsumeASDW("On") ;press down
LButton Up::ConsumeASDW("Off") ;release
ConsumeASDW(OnOff)
{
for each, key in StrSplit("asdw")
Hotkey, % key, Consumer, % OnOff
}
Consumer()
{
Return
}
You've got the right idea, but what you currently have will be auto-executed at the beginning of the script, and after one run through of checking whether or not the LMB is held down, the script will stop doing anything.
My approach, using the $ modifier with hotkeys to make sure the hotkey doesn't recursively trigger itself.
$w::
if (GetKeyState("LButton", "P"))
return
Send w
return
$a::
if (GetKeyState("LButton", "P"))
return
Send a
return
$s::
if (GetKeyState("LButton", "P"))
return
Send s
return
$d::
if (GetKeyState("LButton", "P"))
return
Send d
return
There might be some more efficient way of declaring the condition of the hotkeys using the #If directive, but this should the job that you need it to.

Toggle keys in autohotkey

My goal is mapping WASD to the 4 arrow buttons on the keyboard and make 1 'Suspend' the script while z exits it. That was easy enough. Now I'd like a and d only apply conditionally. I look at the docs and I have no idea what's wrong here. I think I'm either using the if statement wrong or Left/Right doesn't work in if statements in which case I have no idea what to do.
#SingleInstance
a::if(UseAD) Left
d::if(UseAD) Right
1::Suspend
2::UseAD:=!UseAD
w::Up
s::Down
z::ExitApp
Try this:
#SingleInstance
$a::Send % UseAD ? "{Left}" : "a"
$d::Send % UseAD ? "{Right}" : "d"
1::Suspend
2::UseAD:=!UseAD
w::Up
s::Down
z::ExitApp
Okay now a break down.
Your If statement wasn't being evaluated correctly. The following line of code after the condition is met is what is run. Like so:
If (true)
do this
Your Hotkey is also wrong for a Multi lined statement. Essentially a single lined Hotkey is a basically a Send command for whatever key or keys specified on that line (unless you specify an assignment/function/command etc...) it will act as a Send Command does. To have an If evaluation requires multiple lines. When you specify a hotkey and you want an evaluation that will require multiple lines you, and must return from a Multi-Lined Hotkey same a Sub Routine:
a::
Code goes here
more code
etc..
Return
b::AnotherHotkey
etc..
Okay so lets plug this Logic in with your code:
#SingleInstance
a::
if(UseAD)
Left
return
d::
if(UseAD)
Right
return
1::Suspend
2::UseAD:=!UseAD
w::Up
s::Down
z::ExitApp
If you run this you'll get an Error about the Text Left... that is because instead of our Hotkey acting as Send command it's acting as a Sub Routine so we have to specify Send command with Left:
a::
if(UseAD)
Send, Left
return
But this isn't correct either, now it's sending the word Left instead of the Key left.. so again we have add Brackets around our named key like so:
a::
if(UseAD)
Send, {Left}
return
Okay, now a and b are not being sent when UseAD is False, so we must Send them by specifying with Else like so:
a::
if(UseAD)
Send, {Left}
else
Send, a
return
Now we run this code and press a or b get an Max Hotkeys reached message because our code is triggering the Hotkey in an Infinate loop. We need to specify our code in such a way that it will not trigger itself, like so:
$a::
if(UseAD)
Send, {Left}
else
Send, a
return
If you notice we have added a $ symbol in front of our hotkey, this adds a keyboard Hook to that Hotkey and will prevent the the script from triggering that hotkey itself. This is now a complete working script but looks entirely different from the first code I posted. That is because I like typing less lines, if I can.
In the first code sample I'm using a Forced Expression % on the Send command and Ternary ? : to evaluate UseAD and if true send Left key if false send the letter, exactly the same as above code, just more concise.

Autohotkey. Hold two buttons and tap another to increase volume

I got stuck building an ahk shortcut script to increase / decrease Volume. The idea was to hold down LAlt+LShift and tap F12 to increase one step per tap.
The order in which LAlt and LShift are pressed shouldn't matter.
I came up with this so far:
!+::
While (GetKeyState("LShift","P")) and (GetKeyState("LAlt","P"))
{
F12::Send {Volume_Up}
}
Return
But somehow it increases the volume on holding LAlt and taping F12. LShift gets igronred..
What's wrong with that...
This
F12::Send {Volume_Up}
isn't a command, it's a hotkey assignment. You cannot use it within executable context. It is actually the short form for:
F12::
send {volume_up}
return
You wouldn't wanna have a return somewhere in between the lines which should be executed, would you.
As can be read in the documentation, you can only combine two Hotkeys for an action easily, like a & b::msgbox, you pressed a and b. E.g. for a,b AND c, you'd need some workaround like the crossed out, old answer below.
BUT you can add as many modifiers to your hotkey as you want. Modifiers are ! alt, + shift, # win and so on (please have a look # http://ahkscript.org/docs/Hotkeys.htm#Symbols).
So you can simply use
<!+F12::send {volume_up}
-
So, your aim is simply to have volume_up be fired when three Hotkeys are being pressed. You can achieve it like this:
#if getKeyState("LShift", "P")
*<!F12::send {volume_up}
#if
or
*<!F12::
if(getKeyState("LShift","P"))
send {volume_up}
return
For the meaning of * and < and other possible modifiers, see http://ahkscript.org/docs/Hotkeys.htm#Symbols
Your approach wasn't too bad. It would have worked if you had used the Hotkey command instead of an actual hotkey assignment. Still that would have been unneeded work

Shortcuts key replacemento with AutoHotkey

I just started using Autohotkey (I am a noob with it) for remapping some key combinations like CTRL+TAB (which is good if you are using your left hand) to be accessible while using your right hand.
My initial script is the following:
RControl & RShift::
{
send {LControl down}{tab}{LControl up}
return
}
It works fine, but while switching tabs in Visual Studio, for example, I cannot hold the CTRL key to keep switching tabs, I can only switch between 2 tabs.
Does anyone know if it is possible to achieve this kind of functionality with Autohotkey?
Thanks in advance.
You don't need the { } around the hotkey body. Hotkeys simply start with :: and end with return. Braces are only needed in functions afaik.
send {LControl down}{tab}{LControl up} could be expressed easier by send ^{tab} which is Ctrl+Tab. The tab-switch in VS also works with right RCtrl.
In either way, this does not work because of the send {ctrl up}. Ctrl needs to stay pressed down in order for the "Active files" window to stay open. Try:
RControl & RShift::send {RCtrl down}{tab}

Autohotkey - multiple scripts and different language issues

I use autohotkey to simplify copying, using Alt+W instead of Ctrl+C. However, I often switch my keyboard to a Hebrew layout, so the w key is now the ' key. Then the autohotkey script for w doesn't work.
I tried to write a second script into the same file but it doesn't get activated when I press Alt+' when I'm in the Hebrew layout. I'm not sure whether it's my syntax or something else, any ideas?
This is my code:
!w::
Send, {ctrl down}{a down}{a up}{c down}{c up}{ctrl up}
return
!'::
Send, {ctrl down}{a down}{a up}{c down}{c up}{ctrl up}
return
Thanks!
Catching Alt-' with the code you used works in other keyboard layouts (like the German layout) so your syntax looks OK to me.
To solve your problem I'd start the autohotkey help file.
Read "List of Keys, Mouse Buttons, and Joystick Controls"
where the section on "Special Keys" explains how to attempt
to catch inrecognized keys via the "keyboard hook".
Basically it describes how to find out the !' scancode which
you then can use as a hotkey alternative.
It is worth to try to use the virtual/scan codes of keys, instead names, This example uses the virtual code (vkXX):
;~ SetKeyDelay, keyDelay:=25, pressDuration:=25 ; details for SendEvent mode.
!vk57:: ; w/'/я... (en/he/ru...)
Send, {CtrlDown}{vk41}{vk43}{CtrlUp}
KeyWait, vk57
;~ Do something by release this key, if necessary...
Return