Using multiple modifier symbols in autohotkey script - autohotkey

I'm new to autohotkey and I got stuck since other at the following, quite simple problem:
I want to map Alt + Shift + b to the c key.
And the following code:
!+b::c
(That is the whole script)
Doesn't work. When I press Alt + Shift + b at the same time, nothing happens.
What am I doing wrong?

!+b::c means as much as "when alt shift b is pressed, do c". But c is no action. State send c instead:
!+b::send c
Also note that when you want to execute more than just one send command, you can also expand the trunk and finish it with a return:
!+b::
send c
msgBox, other things
return
edit - wait a minute. If I remember right, a::b is a remapping of the a key to behave like b. So !+b::c should also work, shouldn't it. I'm confused now.
edit - well !+b::c does not send c but it sends !+c. This does not make any sense

Related

Alt HMC in Autohotkey

I am trying to remap a function key like F4 to do an ALT then press H + M + C.
Tried reading the docs but was not successful in getting my answer.
I actually thought this may work but it's not.
F4::!hmc
That was probably working, but AutoHotkey runs too fast for most applications to pick up on the macros. It looks like you want to manipulate Word or some sort of ribbon menu. Try this:
SetKeyDelay, 50 ; Increase this to increase the delay
F4::!mhc
You could also try switch our your ! for {Alt} and see if you get any improvements there. Let me know if this works for you.

Emulating Ctrl + Spacebar + AlphabeticalKey with Autohotkey

My problem :
^space & c::
send {F2}
send {Escape}
but it didn't work, how do I emulate Ctrl+Space + AlphabeticaklKey ?
As my previous speakers said, it can't be done easily. Here's my suggestion, it seems to work fine:
^space::
Loop {
if(GetKeyState("c")) {
break
}
if(!GetKeyState("CTRL") || !GetKeyState("SPACE")) {
return
}
Sleep, 50
}
msgbox, You have pressed CTRL+SPACE+C
return
The code is pretty self-explanatory. When CTRL + SPACE is pressed, it waits until either one of both is released or C is pressed. The latter triggers the actual functionality, otherwise it will return.
I actually don't like it very much, because theoretically it may fail in some cases (e.g. when CTRL + SPACE + C is pressed and released before the execution reaches the check for the state of C; although that seems very unlikely).
Update
There's also a way using #If. I recommend using that since it's more sophisticated and reliable. This is due to the fact that it doesn't need any loops:
#If GetKeyState("SPACE")
^c::Msgbox, You have pressed CTRL+SPACE+C
#If GetKeyState("c")
^space::Msgbox, You have pressed CTRL+SPACE+C
As far as I know, you can only combine two non-hotkey keys with the syntax:
space & c:: msgbox space and c
You can read it here
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
Trying to use control as well like in: space & c & control or space & ^c or any other combination will result in compile error.
My recommendation is that you don't combine that three keys together. Look for a pure hotkey combination or use another more or less useless key.
#!c:: windows + alt + c
AppsKey & c::
Remember that if you use a normal key as modificator, you have to remap it to itself to keep the original functionality, for example with the menu key (appskey):
AppsKey:: Send {Appskey}
AppsKey & c:: ;do what you want
There are actually a couple ways to get help. First of all the authors of this language have moved to a new domain ahkscript.org. It is always welcome to ask questions like these in our forum. I just happened to be digging through this site today and saw this by accident.
When you have more than one line of code after a hotkey you need to have a return follow it:
^space & c::
send {F2}
send {Escape}
return
Hope that helps

AutoHotKey - Key spamming does not work like I want it to

Key Spam does not work so good.
Here is the code:
Loop
{
If GetKeyState("z", "P")
send w
If GetKeyState("g", "P")
send a
If GetKeyState("j", "P")
send d
If GetKeyState("h", "P")
send s
}
but when I hold z or zg together, then the original keys z and zg come all time once or twice between the w or wa output.
What can I write that the keys z+g+h+j never will be seen in the text file only w+a+s+d if I run this script?
Karoline, you are going about it the wrong way. Autohotkey was designed to do just what you really want to do.
As MCL says in his comment, you need only to map your keys to a send function
Put this in your script:
z::send w
g::send a
j::send d
h::send s
Now, when you push z it will type w instead.
Keep in mind that this is global over your entire computer unless you limit it to notepad using IfWinActive. The script will not exit on its own.
but this doenst work like i want
i want that i can press g+z same time or z+j same time or g+h same time or h+j same time
and that i get then awawawawaw or asasasasasasas or wdwdwdwdwdwdwd
that when i press 2 buttons same time it switch output ever 1 char
and when i use your answer and holz z it spams wwwwwwwwwwwwwwwwwwwwwwwwwwwww
and if if press then z+g it only continou spaming wwwwwwwwwwwwww not wawawawawawawawaw
thans
Karoline
According to your "answer", you are targeting a keyboard behaviour that's not standard. That is, using remapped keys with AHK or not, when pressing two letter keys simultaneously, solely the key pressed at last will continue firing.
Here's an example on how you can achieve an alternating behaviour instead:
SendMode, Input
g & z::
z & g::
Send, aw
return
g::Send, a
+g::Send, A
z::Send, w
+z::Send, W
You will have to explicitely define every custom combination with an & modifier, which makes them prefix keys. This comes with an upside and with a small downside: The upside is, you can now keep pressing your combination and it will continue firing two keys in an alternating fashion; no loop or the like required. The downside: You need to reconstruct prefix hotkeys' original behaviour. In our example, that's sending a lowercase or uppercase letter.

Autohotkey send key, let it trigger other hotkeys (#InputLevel confusion)

I want to create a hotkey that sends some key, and then another hotkey for that very just sent key, that in turn sends a third key.
That seems to be possible, using #InputLevel:
#InputLevel 1
a::b
#InputLevel 0
b::c
The above works as intended: By pressing a I get c.
However, I want not only to remap the first key: I want to do more before sending the key. So I thought I could just rewrite the above a little bit:
#InputLevel 1
Hotkey *a, foo
#InputLevel 0
b::c
foo:
; Do something more here …
SendInput {Blind}b
return
The above however does not work as intended: By pressing a I get b (not c).
Update: #Robert Ilbrink reminded me that you can execute more than one command, without using the Hotkey command:
#InputLevel 1
*a::
; Do something here …
SendEvent {Blind}b
return
#InputLevel 0
b::c
The above does give the intended effect: Pressing a results in c. However, I have to rephrase my problem. I guess the problem is: I need to set the hotkeys dynamically, which means I have to use the Hotkey command with a label (as far as I know). (Also notice that I use SendEvent above. Using SendInput produces a b. Odd.)
(End of update.)
I know there is a companion command to #InputLevel—SendLevel—which might be relevant. I've tried putting it many places but it has never made any difference.
So, that was the reduced, theoretical example. Remapping a to b to c is of course useless in reality (and the net result could of course be achieved by a::c). On to my use case. Just keep in mind that if it turns out that the "real" solution means doing what I'm trying to do some other way, I'm still interested in knowing more about #InputLevel and SendLevel, and why my example does not work as intended.
I'm working on implementing dual-role modifier keys. For example, send ) when pressing RShift alone, but RShift+key when pressed together with some other key. Basically, RShift on keydown, and RShift up and ) on keyup. However, that has one flaw: Even when combining RShift with some other key, ) is still sent. So the script needs to know when there has been a combination. My solution is to add hotkeys to all letter keys, the arrow keys and some other keys, like this:
for comboKey in filteredComboKeys {
Hotkey % "*" comboKey, Dual_comboKey
}
; Later in script:
Dual_comboKey:
; The following function lets the dual-role modifier keys know that they have
; been combined with another key (and a few other things, which I don't think
; are important for the issue.)
Dual.combo() ;
key := Dual.cleanKey(A_ThisHotkey)
SendInput {Blind}%key%
return
The above solution works very well for my purpose—except that the break all remappings and other hotkeys the user might have made: These simply never occur.
Why not:
a::
; Do something
Send, b
Return
As far as I can gather, #InputLevel doesn't bite on the Hotkey command. However, I stumbled on a solution for one of the snippets I originally posted:
Hotkey *a, foo
b::c
foo:
; Do something more here …
SendLevel 1
SetKeyDelay 0 ; Optional; Only affects this hotkey.
SendEvent {Blind}b
return
Note that SendEvent must be used. SendInput produces b. SendPlay produces nothing at all. I don't know why.
However, this technique won't work if you want to send the hotkey itself. Then you end up in an infinite loop. Using the keyboard hook does not help, since SendLevel overrides it.
So, again I have an answer the solves one of the initial examples, but does not help me in reality. I need to send the hotkey itself. I guess I have to let the user remap their keys using my script. Sigh.
Update:
I've published my dual-role modifiers script now, in case anyone is interested in more details, and how I deal with the problems.
Update:
I've updated my dual-role modifiers script. I now stay away from the Hotkey command. It's easier when dealing with this kind of thing, I think.
By now (starting Autohotkey 1.1.01), this can be achieved quite easily like so:
~Shift up::
IfInString, A_PriorKey, Shift
{
Send )
}
return

Autohotkey: Commands with Alt Key Working Properly only if not Restricted to a Specific Application

I'm trying to add custom keyboard commands to an application using Autohotkey.
In many of these hotkeys I would like to use the alt key in combination with some other key of my choice (any of the standard letters).
All works fine as long as I don't restrict their usage in such a manner that they work in the target application only (via the #IfWinActive directive ). If I do so, the hotkeys themselves still work, however their behavior is very strange.
I found that they get activated either if
a) I hold down the alt key and then press the second key (in my case the 'b' key) twice
or
b) I use this hotkey two times consecutively with a very short delay between the two triggerings
- The above two cases might actually be 1 case. I'm not sure...
I have no problems when doing the same with Shift or CTRL.
The 'b' key is not what's causing the problem - no alt + 'letter' combination works.
I have tried all SendModes, but so far with no effect.
Code sample:
#IfWinActive, MyAppTitle ahk_class MyAppClass
!b::
click 367, 86
return
Alt+letter commands in AutoHotkey such as !b work without issue. It's possible the version at the time of this post contained certain bugs or was out of date from the current version.
For your code, it could be done like so:
!b::
WinGetTitle, Title, A
if (RegExMatch(Title, "MyAppTitle"))
{
MouseClick, left, 367, 86
}
return