I would like to assign the number 1 so that when I press it the result is to send to the computer qx and then enter.
1:: Send, qx{ENTER}
q:: Send, jx{Enter}
But then I also want to assign the letter q to send something else to the computer. Is it possible to do this? I'm concerned that if I assigned 1 to something that involves q, then whenever I press 1 q will also be called, and we'll end up in a loop.
Is there some way to fix it so AHK 'knows' when qx gets sent that I don't want to call the q function (and hence jx)?
Good thinking. The AutoHotKey developers have thought about that and introduced the $ to prevent this "loop"
example:
$1::Send, q
$q::Send, 1
Pressing 1 will generate a q, but due to the $ it will NOT trigger the second hotkey and vise versa.
So by pacing a $ in front of the q, you will prevent this loop in your situation.
Related
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 code to receive CTRL+X while pressing CTRL+V twice
Can anyone help with this?
Many thanks!
Assuming we are talking about Ctrl+C, not V, and assuming you want to keep the original Ctrl+C function but also use it for Ctrl+X when pressing twice in a short time:
#persistent
Transform, cC, Chr, 3 ; store the value of ctrlC into cC.
hotkey, $^c, ctrlC, ON ; this is basically the same as if to say $^c::..., but only deactivable
return
ctrlC:
hotkey, $^c, ctrlC, OFF
input, key, M L1 T0.2
hotkey, $^c, ctrlC, ON
if errorlevel = timeout
send ^c
else if key = %cC%
send ^x
else
send %key%
return
should do..
also see Input for further information. I used this little hotkey-command-trick in order to temporarily disable the Ctrl+C-Hotkey, because otherwise input would not recognize the second c
In this example, I set timeout to 0.2 seconds. Change it to your convenience.
About your capslock idea - sounds like a good idea to me, but anyways, we're not a code-provider network. The command getKeyState should help you started.
I am not able to switch left shift key to right shift key in AutoHotkey. I tried this code to switch but it worked perfectly for up, down, left and right arrows but didn't work for shift keys. Here's the code..
up::w
down::s
left::a
right::d
freerun::LShift
Numpad8::up
Numpad8::up
Numpad5::down
Numpad4::left
Numpad6::right
RShift::freerun
NumpadAdd::Enter
NumpadEnter::Backspace
You must use $ sign, otherwise lshift will fire rshift, which fires lahift. This will go on forever. $ prevents key from firing by send.
$LShift::RShift
$RShift::LShift
There are two important modifiers in AutoHotKey: ~ and $
Without these modifiers hotkey is intercepted and processed. It doesn't propagate. however k::m replaces k with m. k::k causes infinite loop.
~k::m allows k to go through and them prints m. Result is km
~k::k is a fork bomb. It sends kk for each k
$k::m is ignored if k came from AHK and fires if k came from keyboard.
h::k
$k::m
would then produce h -> k and k -> m replacements.
You need to use $LShift::RShift to avoid the loop.
Try this
LShift::RShift
RShift::LShift
You should use $ to prevent an infinite firing loop. Use this:
$LShift::RShift
$RShift::LShift
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.
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