Negating keypress in AHK - autohotkey

I'm playing a game and it acts wonky when I press 3 buttons at the same time. I need the resulting input of holding down "A S D" to be only "S".
Something like
#SingleInstance
if getkeystate("a")
if getkeystate("s")
if getkeystate("d")
input "s"

A simple, but perhaps not so short combination of hotkeys and their up variants will do the trick. This script works like you intended, but only with buttons a and s. When s is held down, a does nothing. When s is not held down, a acquires its previous state.
#SingleInstance, Force
SetBatchLines, -1
global a_down = false
global s_down = false
a::
a_down = true
if( %s_down% = true )
return
Send, {a down}
return
a up::
a_down = false
if( %s_down% = true )
return
Send, {a up}
return
s::
s_down = true
if( %a_down% = true )
Send, {a up}
Send, {s down}
return
s up::
s_down = false
if( %a_down% = true )
Send, {a down}
Send, {s up}
return
In the spirit of StackOverflow, I will not post the complete script that will work with all three keys. That is left as an exercise to the reader.

I need the resulting input of holding down "A S D" to be only "S".
By "Input" you mean a Send command?? Please see Beginner tutorial - hotkeys and hotstrings.
If your task would be to behave A+S like S, you'd use
a & s::
send s
return
But you're asking for three keys which needs some workaround
#if getKeyState("d")
a & s::
send s
return
#if
or
a & s::
if getkeystate("d")
{
send s
}
return

Related

AHK, not working as expected

trying to make a toggle-able loop, seems to be not sending e at all, help please?
myvar := false
k::
myvar := true ? false : true
return
while (myvar)
{
Send, e
Sleep 100
}
Here is my suggestion:
k::SetTimer, SendLetterE, % (Toggle:=!Toggle) ? 100 : "Off"
SendLetterE() {
Send, e
}
You can assign another key to pause / resume. In this case k will toggle and F12 will run indefinitely (so just use k to toggle).
k::
Hotkey, F12, toggle
return
F12::
while(true)
{
Send, e
Sleep 100
}
Could also try Loop instead of while(true)
k::
pause, toggle
F12::
Loop,
{
Send e
Sleep, 100
}
return
referenced from AutoHotkey forum.

Send only if key was pressed alone

I'd like to remap my windows key to something else, but also I'd like to keep all windows key based shortcut.
In pseudo code it would be something like this:
when LWin Down
until LWin Up
if not LWin down
abort
else
execute command
Release the left windows key within 0,3 seconds after pressing it, to do something else (e.g. to send a):
~LWin::
KeyWait, LWin
return
~LWin Up::
Send {LWin Up}
If (A_PriorHotKey = "~LWin" AND A_TimeSincePriorHotkey < 300)
Send, a
; else ; another action after long press (not recommendet)
; Send, b
return
EDIT:
Try also this:
LWin up::
If (A_PriorKey = "LWin")
Send a
return
; In this case its necessary to define a custom combination by using "&" or "<#"
; to avoid that LWin loses its original function as a modifier key:
<#d:: Send #d ; <# means LWin

Disable/Block a Key with another Key while its pressed and held down

So in this game im moving my charachter with the WASD keys, but if i hold down the A and D key at the same time,
the game register that as a forward movement (W key |) so the charachter starts to move forward instead of the strafe actions (Left) \ (right) /.
So i need a code which is prevents the A and D key simultaneous pressing.
CHECK THIS GIF, SO U CAN SEE WHAT I MEAN!
I want A and D override each other (Im not using the W key), because if i hit both A and D at the same time my character moves forward, not like this \ /
and i want to avoid the forward movements.
I want insantly changed fast Left \ and Right / strafing only.
Here is the code what i got so far:
~a::
If (GetKeyState("d", "p"))
{
Send {d up}
d = 0
}
Return
~d::
If (GetKeyState("a", "p"))
{
Send {a up}
a = 0
}
Return
a up::
If (d)
{
Send {d down}
d = 0
}
Return
d up::
If (a)
{
Send {a down}
a = 0
}
Return
Basicly this code almost working.
The problem is if i don't change the numbers i can't change directions continuously i need to let go the keys. It stops after 1 direction change. If i change the numbers its working, but after a few direction change its getting toggled either left or right. Even if i let it go its moving left or right....
Any ideas? thx
This should work. Try it and let me know.
$*a::
$*d::
SendInput, {a Up}{d Up}
StringReplace, hk, A_ThisHotkey, % "$*"
SendInput, {%hk% Down}
KeyWait, % hk
Send, {a Up}{d Up}
return
EDIT: You can play around with the code below. Maybe it will help you out
#SingleInstance, force
#Persistent
#NoEnv
#MaxThreadsPerHotkey, 1
~a & d::
~d & a::
Send, {a up}
key := "d"
SetTimer, pressdown, 10
return
~d::key := "d"
~a::key := "a"
~a up::key := "d"
~d up::key := "a"
pressdown:
if GetKeyState(key, "p")
{
SendInput, {%key% down}
SetTimer, pressdown, 30
}
else {
SetTimer, pressdown, Off
SendInput, {%key% up}
}
return
This script cannot allow A, or D to be simultaneously pressed.

Unable to emulate mouse buttons with combination keys

I'd like to assign some key combinations to mouse buttons.
I 'm going to use 'vk1Dsc07B' as a virtual prefix key,
and I'll use 'v' as LButton, 'c' as MButton and 'x' as RButton.
I tried several ways, but I failed. I could click, however, I coudn't drag properly.
Once I tried to drag an object, the pointer grab and release it every 0.1 seconds.
The problem is, I guess, that the key events are sent repeatedly unlike mouse buttons'.
I'm looking for a code which acts as following:
keep a mouse button pressed continuously, NOT REPEATEDLY, while I'm pressing combination keys
change a mouse button up when I release the one key, other than virtual prefix key, of the combination keys
Here is one of my codes:
vk1Dsc07B::Return ; deactivate 'Muhenkan' key in order to use it just as a prefix key
vk1Dsc07B & v::Click,L,D Return
vk1Dsc07B & c::Click,M,D Return
vk1Dsc07B & x::Click,R,D Return
vk1Dsc07B & v Up::Click,L,U Return
vk1Dsc07B & c Up::Click,M,U Return
vk1Dsc07B & x Up::Click,R,U Return
another sample:
vk1Dsc07B::Return ; deactivate 'Muhenkan' key in order to use it just as a prefix key
vk1Dsc07B & v::Send {Blind}{LButton down}
vk1Dsc07B & c::Send {Blind}{MButton down}
vk1Dsc07B & x::Send {Blind}{RButton down}
vk1Dsc07B & v Up::Send {Blind}{LButton up}
vk1Dsc07B & c Up::Send {Blind}{MButton up}
vk1Dsc07B & x Up::Send {Blind}{RButton up}
Maybe most of you don't have 'vk1Dsc07B' key, so please replace it a certain key.
Glad to hear any idea:)
Sincerely,
What you are trying to achieve is remapping two keys to one. AutoHotkey documentation says:
Although a pair of keys cannot be directly remapped to single key (e.g. it's invalid to write a & c::b), this effect can be achieved by explicitly adding the up and down hotkeys [link]
So, the second solution of yours should actually work:
vk1Dsc07B::return ; you don't need this line. vk1Dsc07B is deactiated by default because of the other hotkeys
vk1Dsc07B & v::Send {Blind}{LButton down}
vk1Dsc07B & v Up::Send {Blind}{LButton up}
; and you need the `{Blind}` keyword here, do you??
, but it doesn't. This only works with 'normal' keys like send {a down}. The problem is that when you hold down vk1Dsc07B & v, {LButton down} will be sent repeatedly. This leads to "the pointer grab and release it every 0.1 seconds".
So, we'll have to look for another way, trying to have {LButton down} be sent only once, when the hotkey is triggered.
I came up with the following solution which stores the hotkey trigger in a variable:
Ltriggered := false
Mtriggered := false
Rtriggered := false
vk1Dsc07B & v::
if(!Ltriggered) {
Send {LButton down}
Ltriggered := true
}
return
vk1Dsc07B & v Up::
Send {LButton up}
Ltriggered := false
return
vk1Dsc07B & c::
if(!Mtriggered) {
Send {MButton down}
Mtriggered := true
}
return
vk1Dsc07B & c Up::
Send {MButton up}
Mtriggered := false
return
vk1Dsc07B & x::
if(!Rtriggered) {
Send {RButton down}
Rtriggered := true
}
return
vk1Dsc07B & x Up::
Send {RButton up}
Rtriggered := false
return

Shift Key Training Wheels and Shift Parenthesis Remap

I'm looking to use AutoHotKey to modify the functionality of my shift keys. The functionality is described in Steve Losh's Blog entry here. Specifically, I'd like my shift keys to do the following:
If LShift or RShift is pressed and released in under 300 ms with no other keys being pressed in between, send ( or ), respectively.
If LShift and RShift are "rolled" together (press LShift, press RShift, release LShift, release RShift, etc.) in under 300ms, send () or )(.
If a shift key is used improperly (LShift and S, RShift and K, etc.) then nothing happens.
I've been having issues with the 300ms requirement and the "rolling" functionality. Specifically, I'm having issues with only being able to detect when the key is released due to the hotkey combos such as:
LShift & 0:: return
This is where I'm at so far:
LShift::
Send {LShift Down}
KeyWait, LShift
Send {LShift Up}
if (A_TimeSinceThisHotkey < 300){
if (A_PriorKey = "LShift")
{
Send {)}
}
}
return
I don't see a reason to use a 300 ms timeout anyway, it seems unreliable and unnecessary.
Have a look at this commented code, it is short and efficient, and seems to meet all of your requirements:
LShift::Send, (
RShift::Send, )
LShift & RShift:: Send, ()
RShift & LShift:: Send, )(
/* Put your unwanted combinations here
* and let them do nothing
*/
LShift & q::return
RShift & y::return
Edit:
Since LShift and RShift already are prefix hotkeys, I left out the trick described here.
MCL's answer is close but when I tested it I found that shift-clicking didn't select text. Here's a version with a passthrough to allow shift-clicking to work.
;shift to parens
LShift::Send, (
RShift::Send, )
LShift & RShift:: Send, ()
RShift & LShift:: Send, )(
;passthrough for shift-click
LShift & LButton::
Send, {LShift Down}{LButton}
Send, {LShift Up}
RShift & LButton::
Send, {RShift Down}{LButton}
Send, {RShift Up}
I don't think the 300ms timeout is possible without either very deep understanding of autohotkey's implementation or actual modification to autohotkey. When I tried to get it to work (using http://www.autohotkey.com/board/topic/98742-remapping-shift-key/) I found that A_PriorHotkey was not consistently populated. I don't think that variable was meant to work with modifier keys this way.
I felt compelled to figure this one out. Here you go!
I basically created a hotkey for every Shift + Letter key combination in order to send the correct key case and also set the Abort value. The Abort value is then referenced whenever one of the Shift keys is pressed in order to determine whether or not to send the corresponding ( or ).
The "Rolling" was accomplished by creating a Hotkey for LShift + RShift (and the opposite). It then looks to see which key is released first to determine () or )(.
Accept if this was what you were looking for!
Loop 26
{
Hotkey, % "~LShift & " Chr(A_Index+96), LetterKey ; Hotkeys for A-Z
Hotkey, % "~RShift & " Chr(A_Index+96), LetterKey ; Hotkeys for A-Z
}
Return
RShift::
LShift::
Abort := 0
keyDown := A_TickCount
Keywait, % A_ThisHotkey
duration := A_TickCount - keyDown
If (duration < 200) and (Abort = 0)
SendInput % (A_ThisHotkey = "LShift") ? "(" : ")"
Send {LShift Up}
Return
RShift & LShift::
LShift & RShift::
Keywait, LShift
If GetKeyState("RShift", "P")
{
Keywait, RShift
Send ()
}
Else
Send )(
Return
LetterKey:
SendInput, % "+" SubStr(A_ThisHotKey, 0, 1)
Abort := 1
Return
EDIT:
Hmm, I seem to be having the same problem as you. I always get a duration of 0 due to the hotkeys.
I found and modified this script on the AutoHotKey Forums. (The original script was prone to type "K(" when you meant to type "K" if you type too quickly, so I've modified it so that shouldn't happen any more)
$LShift Up::send, % getkeystate("LShift") ? "{LShift Up}" : ""
$RShift Up::send, % getkeystate("RShift") ? "{RShift Up}" : ""
~$LShift::
KeyWait, LShift, T0.1 ; wait 100ms to check shift state
if (A_PriorKey = "LShift")
{
send, % getkeystate("LShift") ? "{LShift Down}" : "("
}
KeyWait, LShift
return
~$RShift::
KeyWait, RShift, T0.1 ; wait 100ms to check shift state
if (A_PriorKey = "RShift")
{
send, % getkeystate("RShift") ? "{RShift Down}" : ")"
}
KeyWait, RShift
return