Make a shift key behave like an arrow key
I tried the hotkeys you listed... they worked fine for me and repeated automatically just fine when held down...
#Persistent
Return
#IfWinActive ; Make replacement operate globally
RShift::Up
Up::RShift
You may be able to try a different SendMode
...
RShift::SendInput {Up}
Up::SendInput {RShift}
or...
RShift::SendPlay {Up}
Up::SendPlay {RShift}
Do you have any other programs that are intercepting these or anything like that? Does the key repeat work normally when the script isn't running?
Setting up a custom loop might look something like this...
RShift::
While GetKeyState("RShift", "P") {
Send {Up}
Sleep 50 ; Set delay to taste
}
Return
EDIT
To address the need for other modifiers to work, a '*' may be used with the hotkey, although in the case of having two shift keys it may not work correctly by default. I've added a special case for the shift key detection but I don't know how that would work if you were to throw other modifiers into the mix... in that case you could look at adding the {blind}
modifier to the Send
statements to see if you could get it to work properly.
To address the 'race condition' another pre-repeat delay can also be added before the repeat loop along with an initial send statement (see below).
*Up::SendInput {blind}{RShift Down}
*Up Up::SendInput {blind}{RShift Up}
*RShift::
Send % GetKeyState("LShift", "P") ? "+{Up}" : "{Up}"
Sleep 250 ; Initial delay before repeat
While GetKeyState("RShift", "P") {
Send % GetKeyState("LShift", "P") ? "+{Up}" : "{Up}"
Sleep 100 ; Repeat delay
}
Return
The problem with all of the other answers is that repeated shift presses will be ignored because the previous hotkey subroutine is still being executed. By defualt, #MaxThreadsPerHotkey is 1, and #MaxThreads is 10.
Below are two possible solutions. Both works well for me.
Increase #MaxThreadsPerHotkey (and #MaxThreads)
SendMode Input
#MaxThreads 150
#MaxThreadsPerHotkey 150
; return the send command including any pressed modifier keys
getSendCommand() {
sendCmd = {Up}
sendCmd = % GetKeyState("LAlt", "P") ? "!" . sendCmd : sendCmd
sendCmd = % GetKeyState("LCtrl", "P") ? "^" . sendCmd : sendCmd
sendCmd = % GetKeyState("LShift", "P") ? "+" . sendCmd : sendCmd
sendCmd = % GetKeyState("Win", "P") ? "#" . sendCmd : sendCmd
return sendCmd
}
*$RShift::
; Immediately send an up key
Send % getSendCommand()
Sleep, 450
While GetKeyState("RShift", "P") { ; while key remains pressed
Send % getSendCommand() ; keep sending up keys
Sleep, 30
}
Return
Immediately abort execution when shift key is released
SendMode Input
; return the send command including any pressed modifier keys
getSendCommand() {
sendCmd = {Up}
sendCmd = % GetKeyState("LAlt", "P") ? "!" . sendCmd : sendCmd
sendCmd = % GetKeyState("LCtrl", "P") ? "^" . sendCmd : sendCmd
sendCmd = % GetKeyState("LShift", "P") ? "+" . sendCmd : sendCmd
sendCmd = % GetKeyState("Win", "P") ? "#" . sendCmd : sendCmd
return sendCmd
}
*$RShift::
; Immediately send an up key
Send % getSendCommand()
; Initial wait period (sleep time = 350 ms, execution time ~450 ms)
Loop 35 { ; Check keystate every 10 ms, abort execution as soon as shift is released
Sleep, 10 ; 10 ms is the shortest possible sleep interval
if not GetKeyState("RShift", "P") {
return
}
}
; Start repeating if and while key is still pressed. Stop execution as soon as shift is released
While GetKeyState("RShift", "P") {
Send % getSendCommand()
Loop 2 {
if not GetKeyState("RShift", "P") {
return
}
Sleep, 10
}
}
Return