Windows – Make a shift key behave like an arrow key

autohotkeykeyboard-layoutwindows 10

I have a Windows 10 laptop with a keyboard designed by idiots. They tried to cram the arrow keys where they don't belong, with the result that the up arrow key is between the right shift key and the / key (US keyboard layout). This is one of the stupidest things the designers could have done, because it means that when I go to hit the right shift key (which is most of the time), I end up hitting up arrow instead. This is incredibly annoying.

I found a program called Sharp Keys which allows me to remap the keys such that the up arrow behaves as shift and the right shift behaves as up arrow. Now, at least I can type. However, I've now lost important functionality for the up arrow key. Up arrow (now labeled "shift" on my keyboard) doesn't repeat. So, I can't just hold the key down to move up. Instead, I have to hit the key repeatedly. How can I fix this, so my right shift key behaves like up arrow and my up arrow key behaves like right shift?

EDIT

Following a suggestion from the comments, I installed AutoHotkey. I have the following script:

RShift::Up
Up::RShift

I have the same problem as earlier. But, since AHK is a scripting language, is it possible to use it to change the repeat behavior?

Best Answer

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
Related Question