autohotkey caps lock to ctrl not releasing - autohotkey

I'm using AutoHotkey to map the Caps Lock to Ctrl, and trying to use the Ctrl + K as Tab in Total Commander.
SetCapsLockState AlwaysOff
Capslock::Ctrl
#ifWinActive ahk_class TTOTAL_CMD
^k::Send, {Tab}
#ifWinActive
When i using the Ctrl + K remap with the normal Ctrl, it works fine. But when i trying to use it with the Caps Lock + K, then it works for the first time, but while i'm not releasing the Caps Lock, it sends k instead of Tab. The log says:
008: SetCapslockState,AlwaysOff
009: Return (3.49)
; Hiting Ctrl + K twice.
081: Send,{Tab} (0.02)
081: Return (0.30)
081: Send,{Tab} (0.02)
081: Return (1.59)
; Hiting Caps Lock + K twice.
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl DownTemp}
009: Return (0.47)
081: Send,{Tab} (0.01)
081: Return (0.73)
; The second Tab is missing, a simple K sent.
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl Up}
009: Return (3.06)
Here is the log, when i pressing Caps Lock + K, releasing it, then pressing againg:
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl DownTemp}
009: Return (0.34)
081: Send,{Tab} (0.01)
081: Return (0.08)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl Up}
009: Return (0.34)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl DownTemp}
009: Return (0.19)
081: Send,{Tab} (0.01)
081: Return (0.06)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl Up}
009: Return (3.00)
I think the source of the problem may be in the CapsLock::Ctrl, but i didn't find any solution for it. Somebody meet with this problem?
EDIT:
Another interesting thing is when i sending code instead of a simple key, it works without releasing the caps lock:
^e::PostMessage, 1075, 3005, , , ahk_class TTOTAL_CMD ; cm_SwitchToNextTab=3005;Switch to next Tab (as Ctrl+Tab) (see TOTALCMD.INC file)
The log says:
008: SetCapslockState,AlwaysOff
009: Return (8.88)
; Ctrl + E twice.
058: PostMessage,1075,3005,,,ahk_class TTOTAL_CMD
058: Return (0.36)
058: PostMessage,1075,3005,,,ahk_class TTOTAL_CMD
058: Return (1.76)
009: SetKeyDelay,-1
; Caps Lock + E twice.
009: Send,{Blind}{Ctrl DownTemp}
009: Return (0.34)
058: PostMessage,1075,3005,,,ahk_class TTOTAL_CMD
058: Return (0.39)
058: PostMessage,1075,3005,,,ahk_class TTOTAL_CMD
058: Return (0.28)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl Up}
009: Return (1.47)
; Caps Lock + E twice with releasing.
008: SetCapslockState,AlwaysOff
009: Return (2.54)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl DownTemp}
009: Return (0.34)
058: PostMessage,1075,3005,,,ahk_class TTOTAL_CMD
058: Return (0.09)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl Up}
009: Return (0.25)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl DownTemp}
009: Return (0.23)
058: PostMessage,1075,3005,,,ahk_class TTOTAL_CMD
058: Return (0.08)
009: SetKeyDelay,-1
009: Send,{Blind}{Ctrl Up}
009: Return (1.98)

I remember running into odd issues like this when I was doing CapsLock remaps as well. Instead of mapping CapsLock to control and then using that combination in your hotkey, you could set CapsLock to do nothing but check the key's state in the #If directive. I would think this would resolve most of those odd issues.
SetCapsLockState, AlwaysOff
CapsLock::Return
#If WinActive("ahk_class TTOTAL_CMD") and GetKeyState("CapsLock", "P")
k::Send, {Tab}

I personally would just check if your window is active on ^k keypress and go from there. I used Untitled - Notepad so I could test.
CapsLock::Ctrl
^k::
{
IfWinActive, Untitled - Notepad
SendInput, {tab}
else
Msgbox
return
}

Related

Auto hot key mapping to switch Control and Alt ^<+Tab::ShiftAltTab does not work

I'd like to use the following Auto Hot Key shortcuts to switch CTRL and ALT:
LCtrl & Tab::AltTab
return
^<+Tab::ShiftAltTab
return
But I've got an error The AltTab hotkey "^<+Tab" must specify which key (L or R).
Changed then I get another error: ... must have exactly one modifier/prefix.
<^<+Tab::ShiftAltTab
return
I found my question asked on Reddit too but no answer there:
https://www.reddit.com/r/AutoHotkey/comments/bb5xlv/tab_for_alttab_tab_for_shiftalttab_how
Try this
; LCtrl + Tab
<^Tab::
Send, {Alt Down}{Tab}
KeyWait, LCtrl ; waits for LCtrl to be relesead
Send, {Alt Up}
return
; LCtrl + LShift + Tab
<^<+Tab::
Send, {Alt Down}{Shift Down}{Tab}
KeyWait, LCtrl
KeyWait, LShift
Send, {Alt Up}
return

Toggle Shift for Single Keypress

I am trying to turn my shift key into a CapsLock of sorts. The goal being that, when Shift is pressed, it shifts the next key to be pressed (eliminating the need to hold down the shift key), similar to the function of StickyKeys but only for the Shift key. I am able to toggle the Shift key using:
LShift:: Send % "{Blind}{LShift " . ((lshift:=!lshift) ? "Down}" : "Up}")
But that requires me to press Shift again, basically turning it into a CapsLock. How can I have this action only last for one keypress?
This should do:
$LShift::
SendInput, {LShift Down}
KeyWait, LShift
SendInput, {LShift Down}
Input, Key, L1 V
SendInput, {LShift Up}
Return
edit:
$*LShift::
SendInput, {LShift Down}
Input, Key, L1 M V
If GetKeyState("LShift", "P")
KeyWait, LShift
SendInput, {LShift Up}
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

Capslock + s + m in AutoHotKey

My full goal is to be able to hold down Capslock + s, which will convert the keys uiojklm,. to work like the 10-key number pad.
So as a first step, I am trying to map Capslock + s + m to the number 1
SetCapslockState AlwaysOff
Capslock & s::
keywait, m, d, t0.6
If (!ErrorLevel) {
SendInput {1}
} Return
I based my current code off of the answer here: Alt + Space + key in autohotkey
When I press Capslock + s + m, it prints out m1. How do I stop the m from printing?
Here is an alternative solution. You MUST have AutoHotKey_L for this to work since the traditional AutoHotKey does not support #if.
CapsLock & s::
Flag:=!Flag
If (Flag)
TrayTip, AutoHotKey, Numpad ON, 1
Else
TrayTip, AutoHotKey, Numpad OFF, 1
Return
#If (Flag)
m::Send, 0
k::Send, 1
#If
In the first block you toggle a Flag to True/False with CapsLock + s and you show the status with a traytip, then you define the behaviour of certain keys in the next block. Alternatively you could delete the first block and replace the #if (Flag) line with:
#If (GetKeyState("CapsLock", "P") and GetKeyState("s", "P"))
Update:
Tried the following with varying results. The first (commented out) code does use CapsLock + s, but apparently pressing the s key prevents AutoHotKey from seeing certain other key presses (here the letters n,m,i,o,p worked but j,k,l which are on the same hight/scanline on the keyboard were NOT detected)
SetCapsLockState, alwaysoff
/*
Capslock & s::
While, (GetKeyState("CapsLock", "P") and GetKeyState("s", "P"))
{
Input, MyKey, I L1 T0.5
TrayTip, Key:, %MyKey%
if (MyKey = "m")
Send, 1
if (MyKey = "i")
Send, 2
if (MyKey = "k")
Send, 3
if (MyKey = "j")
Send, 4
if (MyKey = "o")
Send, 5
if (MyKey = "p")
Send, 6
}
Return
*/
Just using CapsLock (also on the same like as j,k,l) worked, but that is not what you wanted.
Capslock::
While, (GetKeyState("CapsLock", "P"))
{
Input, MyKey, I L1 T0.5
TrayTip, Key:, %MyKey%
if (MyKey = "m")
Send, 1
if (MyKey = "i")
Send, 2
if (MyKey = "k")
Send, 3
if (MyKey = "j")
Send, 4
if (MyKey = "o")
Send, 5
if (MyKey = "p")
Send, 6
}
Return

Autohotkey macro: trying to remap left-alt to left-win; left-win to left-win with a toggle

I am trying to remap Left Alt to Left Win and Left Win to Left Alt in AutoHotKey.
But I also want to have Shift + F11 to toggle these two remaps.
I know I can do:
LAlt::LWin
LWin::LAlt
but what I can't figure out is the toggle. The following version fails:
Shift & F11::
Hotkey, LAlt, Toggle
Hotkey, LWin, Toggle
return
When I press Shift and F11, it will say:
---------------------------
test.ahk
---------------------------
Error: Nonexistent hotkey. The current thread will exit.
Specifically: LAlt
Line#
001: Return
002: SetKeyDelay,-1
002: Send,{Blind}{LAlt DownTemp}
002: Return
002: SetKeyDelay,-1
002: Send,{Blind}{LAlt Up}
002: Return
---> 006: Hotkey,LAlt,Toggle
007: Hotkey,LWin,Toggle
008: Return
009: Exit
010: Exit
010: Exit
---------------------------
OK
---------------------------
I've been scratching my head for hours.. Any input will be greatly appreciated!
I'm sure it is more verbose than necessary, but I just tried this script and it does something like what you're after. It might send you in the right direction, if nothing else.
#NoEnv
SendMode Input
IsRemapEnabled := false
SetRemapEnabled(false)
SetRemapEnabled(toEnabled)
{
global IsRemapEnabled := toEnabled
}
+F11::
SetRemapEnabled(!IsRemapEnabled)
return
LAlt::
if (IsRemapEnabled)
{
Send,{LWin DOWN}
} else
{
Send,{LAlt DOWN}
}
return
LAlt up::
if (IsRemapEnabled)
{
Send,{LWin UP}
} else
{
Send,{LAlt UP}
}
return
LWin::
if (IsRemapEnabled)
{
Send,{LAlt DOWN}
} else
{
Send,{LWin DOWN}
}
return
LWin UP::
if (IsRemapEnabled)
{
Send,{LAlt UP}
} else
{
Send,{LWin UP}
}
return