Creating a Virtual Numpad with AutoHotKey
I recently built a virtual numpad using AutoHotKey to adapt to my new keyboard setup. I switched to a Kinesis Freestyle2 Blue keyboard, which lacks the built-in numpad I was accustomed to. This became particularly frustrating when starting my workday, as I needed to enter an authenticator code to connect to the corporate VPN. After a few days of struggling with the top-row numbers, I realized I needed a numpad solution that would not add extra hardware to my desk. Separate numpads seemed inefficient and impractical.
Initial Challenges and Solution
Initially, I explored remapping keys using my keyboard's configuration tools, but this approach proved to be cumbersome. Eventually, I found a simple yet effective solution with AutoHotKey. I configured it so that when I hold down the CapsLock key, the letter keys under 7, 8, and 9 remap to function as a full numpad. This allows me to comfortably touch-type numbers with my right hand while holding CapsLock with my left pinky. The script also ensures that CapsLock does not activate inadvertently—it remains off unless explicitly pressed.
Here's a simulation of the experience:
Alt-Code Functionality
Another useful feature of this script is its ability to handle alt-codes. By holding down CapsLock along with the Alt key, I can type an alt-code, and when I release Alt, the corresponding symbol is sent. For example:
♥ <- Alt
+ 9731
This setup has significantly improved my workflow, allowing me to maintain a clean desk space while retaining the functionality I need for efficient input.
The Script
#Requires AutoHotkey v2.0
SetCapsLockState(GetKeyState("CapsLock", "T") ? "AlwaysOn" : "AlwaysOff") ; Prevent capslock from lighting up when first used as modifier.
CapsLock::SetCapsLockState(GetKeyState("CapsLock", "T") ? "AlwaysOff" : "AlwaysOn") ; Set capslock to the opposite state when not used as a hotkey modifier.
CreateNumpadKeys()
CreateNumpadKeys() {
static AltCode := ""
static keyMap := Map(
"m", 0,
",", 0,
"j", 1,
"k", 2,
"l", 3,
"u", 4,
"i", 5,
"o", 6,
"7", 7,
"8", 8,
"9", 9
)
Hotkey "~*Alt up", OnAltUp, "On" ; Create hotkey for when Alt is released.
for key, num in keyMap { ; for-loop each key, value in keyMap.
Hotkey "CapsLock & " key, remap, "On" ; Create hotkeys with CapsLock as the modifier.
}
static remap(ThisKey) {
num := keyMap[SubStr(ThisKey, -1)] ; Get last character from current hotkey, and use it to get number from keyMap.
if GetKeyState("Alt", "P")
AltCode .= num ; If Alt is down, concatenate the number to AltCode variable.
else
Send "{Numpad" num "}" ; If Alt is not down, send the number.
}
static OnAltUp(*) {
if AltCode {
Send "{ASC " AltCode "}" ; When Alt is released send the saved alt code.
AltCode := ""
}
}
}
Making this run at startup
I made this script run when I log into Windows. To do so, I created a shortcut to the script in %appdata%\Microsoft\Windows\Start Menu\Programs\Startup
.