I want to be able to map the Caps Lock Key to Escape if it is not pressed with any other key and Control if it is. How can I do that on Windows 7?


10 Answers 10


You can remap it to Escape with SharpKeys

However, I don't know of a realistic way to perform conditional remapping, other than writing a keyboard driver.

  • 1
    I already have my Caps Lock key mapped to Escape with SharpKeys. Jan 23, 2012 at 14:24

This may have appeared on the previously mentioned vim wikia page after Rich's solution above.

; Author: fwompner gmail com
SetCapsLockState, alwaysoff
Send {LControl Down}
KeyWait, CapsLock
Send {LControl Up}
if ( A_PriorKey = "CapsLock" )
    Send {Esc}

This is not my work, but I've started using it and it works exactly as described, no real caveats, and because it doesn't attempt to map any exceptions (because they are unnecessary) it behaves quite nicely in Chrome (I really wanted it for Vimium).

  • I've been using this script and it works for me. I'm using this for rebinding Caps Lock to Control/Escape for vim.
    – Brandon
    Sep 19, 2016 at 15:04
  • 1
    Works! Just to clarify, it's an AutoHotKey script. Start here: autohotkey.com Oct 26, 2017 at 14:20
  • 1
    For the benefit of readers that may not have clicked through and seen the comments on my gist, it seems this solution only works if you press Caps Lock before pressing Shift. Caps+Shift+X works but Shift+Caps+X doesn't.
    – Rich
    Jan 3, 2018 at 10:12

This is not exactly what you want but very close if you can live with some flaws. Here's an AutoHotKey script:

$CapsLock Up::Send {Escape}

It remaps Caps Lock to Ctrl and sends Escape when you release the key. It took me a while to get used to the Escape key being pressed every time I let go the Caps Lock key. However it's pretty much useless on website textareas because pressing Escape loses the focus on the textarea.

I'm looking for a solution to this though. I might go as far as write some sort of driver/keyboard hook in C if needed, haha.

Vim-specific annoyances: It makes digraphs impossible to type using the Ctrl-K combination and is generally plain annoying before you get used to it. It works well for me though because I'd do anything to avoid Esc and Ctrl keys as much as possible.

  • If you just want to map it to escape, you can simplify this to: $CapsLock::Escape and then immediately return.
    – Kazark
    Apr 14, 2016 at 16:26
  • I'm trying to understand -- so the flaw with the script is that when Caps Lock is pressed and released, both a Ctrl and Escape are sent?
    – Rishi
    Jun 15, 2016 at 16:19
  • Watch out: the AutoHotKey code given here led to all kinds of problems for me. The script given by dragon788, on the other hand, seems to be working well so far.
    – ba_ul
    Feb 11, 2020 at 3:19

Here is a registry entry that maps the caps lock to escape on windows 7.

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,03,00,00,00,3a,00,46,00,01,00,3a,00,00,00,00,00

Save the above to a file with a .reg extension (like mapCapLocks.reg) and import/execute it on your machine. This can be done by clicking that file in the File Explorer, and then signing out and signing in again.

  • Please quote the essential parts of the answer from the reference link(s), as the answer can become invalid if the linked page(s) change. Currently 404 so this answer is useless.
    – DavidPostill
    Feb 12, 2017 at 14:26
  • Excellent points. I will update the answer
    – Stryker
    Feb 12, 2017 at 16:11
  • 4
    This will also map the ScrollLock key to CapsLock. If that's not what you want, use the value hex:00,00,00,00,00,00,00,00,02,00,00,00,01,00,3a,00,00,00,00,00. Useful editor for this map is ScancodeMapping from PlexData.
    – Appleshell
    Jun 22, 2019 at 14:05
  • Thanks @Appleshell. Was looking into this and realised it was also doing that additional remapping. Useful introduction for newbies. And if you want to swap escape with caps lock, use this: hex:00,00,00,00,00,00,00,00,03,00,00,00,01,00,3a,00,3a,00,01,00,00,00,00,00
    – Cloud
    Feb 16 at 22:16
  • Useful site for testing keyboard presses after signing back in
    – Cloud
    Feb 16 at 22:27

I use the following AutoHotkey script for this, adapted from one I found on the Vim Tips Wiki. The implementation is a bit hacky, but it "works for me." (And unlike the other answers on this page as of 2016-09-19, it fully solves the issue without any caveats that I am aware of.)

The original coder noted:

The script also tries to detect and avoid "false positives" where you press Control and another key and release both too quickly, i.e. before the timeout period.

Be sure to tweak the 250ms value depending on how good or bad your keyboard is, and your own reaction time. This is probably something to tweak experimentally to your own liking.

CapsLockCtrlEscape.ahk gist:

g_LastCtrlKeyDownTime := 0
g_AbortSendEsc := false
g_ControlRepeatDetected := false

    if (g_ControlRepeatDetected)

    send,{Ctrl down}
    g_LastCtrlKeyDownTime := A_TickCount
    g_AbortSendEsc := false
    g_ControlRepeatDetected := true


*CapsLock Up::
    send,{Ctrl up}
    g_ControlRepeatDetected := false
    if (g_AbortSendEsc)
    current_time := A_TickCount
    time_elapsed := current_time - g_LastCtrlKeyDownTime
    if (time_elapsed <= 250)
        SendInput {Esc}

    g_AbortSendEsc := true

Actually I think I've built the perfect solution here:

As a Vim user, this is a must for me, and I've been using it with success on Windows for a long time. I just create an entry on HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run with regedit to point to the executable and it simply works.

To compile and install dependencies please check the repository README and main website for Interception.

I've also created a Linux version of the same here:


I was looking for something as similar to this, but unfortunately the AHK scripts from the answers here didn't work well for me.

However, I found a solution that solved this for me on the vim wiki.

  • First, download the following app called dual-key-remap.
  • Extract the zip in a location of your choosing (I store utilities like these in C:\Users\%username%\util\)
  • Open the following directory: C:\Users\%username%\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\ and drag the dual-key-remap.exe file there, while holding ALT to create a shortcut. (Or right click and select 'create shortcut', and move the shortcut to your startup directory).
  • Log in and out. A few seconds after you're logged in the keys will be rebound.

The remapkey.exe program included in the Windows Server 2003 Resource Kit Tools mentioned in this article works nicely in Windows 7.

  • 1
    please avoid using links as answers. instead, try explaining to your best the contents of the links and only then use them as reference. if the link ever gets broken, so does your whole answer. Apr 8, 2013 at 16:08

If you don't mind compiling short source code yourself, then you can use the code below. You need to compile it as Windows console application. E.g., in Visual C++ command prompt you can compile it with

cl /D_WIN32_WINNT=0x0401 remap_capslock.cpp /EHsc /link user32.lib

The key remapping works while the application is running. No need for reboot, log out/in, etc. If you need remapping to work for applications run with admin rights, then you need to run the remapper application as admin also. Have been using it for couple of days already (on Windows 10), so far so good.

// The app allows to remap CapsLock key to Esc (if pressed separately) or to Ctrl (if pressed with other keys).
// This may be useful for Vim.
// To compile from Visual C++ command prompt: 
//    cl /D_WIN32_WINNT=0x0401 remap_capslock.cpp /EHsc /link user32.lib
// Original source (which supported only Caps-Ctrl remapping): https://superuser.com/a/1490007/22750

#include <windows.h>
#include <iostream>
#include <set>

HHOOK hook;
std::set<WORD> keys_down;
bool caps_down = false;
bool caps_was_down_with_another_key = false;

LRESULT CALLBACK keyboardHook(int nCode, WPARAM wParam, LPARAM lParam) {

    if ((p->flags & LLKHF_INJECTED) == 0) {
        std::cout << "nCode=" << nCode << "\twParam=" << wParam << "\tvkCode=" << p->vkCode << "\tscanCode=" << p->scanCode << std::endl;
        bool keyup = wParam == WM_KEYUP || wParam == WM_SYSKEYUP;
        if (p->vkCode == VK_CAPITAL) {
            if (keyup) {
                if (caps_was_down_with_another_key) {
                    std::cout << "Remapping CAPSLOCK UP to CTRL UP" << std::endl;
                    input[0].ki.dwFlags = KEYEVENTF_KEYUP;
                    input[0].ki.wVk = VK_LCONTROL;
                    SendInput(1, input, sizeof (INPUT));
                } else {
                    std::cout << "Remapping CAPSLOCK UP to ESCAPE DOWN&UP" << std::endl;
                    input[0].ki.dwFlags = KEYEVENTF_KEYUP;
                    input[0].ki.wVk = VK_LCONTROL;
                    input[1].ki.dwFlags = 0;
                    input[1].ki.wVk = VK_ESCAPE;
                    input[2].ki.dwFlags = KEYEVENTF_KEYUP;
                    input[2].ki.wVk = VK_ESCAPE;
                    SendInput(3, input, sizeof (INPUT));
                caps_down = false;
                caps_was_down_with_another_key = false;
            } else {
                std::cout << "Remapping CAPSLOCK DOWN to CTRL DOWN" << std::endl;
                caps_down = true;
                input[0].ki.dwFlags = 0;
                input[0].ki.wVk = VK_LCONTROL;
                SendInput(1, input, sizeof (INPUT));
            return 1;
        } else {
            if (keyup) {
            } else {
            std::cout << keys_down.size() << " keys down" << std::endl;
        if (caps_down && !keys_down.empty()) {
            caps_was_down_with_another_key = true;
    return CallNextHookEx(hook, nCode, wParam, lParam);

int main(int argc, char **argv){
    MSG messages;
    hook = SetWindowsHookEx(WH_KEYBOARD_LL, keyboardHook, NULL, 0);
    if (hook == NULL) {
        std::cout << "Error " << GetLastError() << std::endl;
        return 1;
    std::cout << "Mapping ??? CAPSLOCK=>LCTRL and LCTRL=>CAPSLOCK..." << std::endl;
    while (GetMessage (&messages, NULL, 0, 0)) {
    return 0;

I don't have enough reputation to comment on the answer that worked for me. I still upvoted it though.

pepper-chico's answer worked for me.

Caps Lock key behaves as Escape key if pressed on its own. And behaves like Ctrl key if combined with others. I also have the same use case for this. Vim.

The instruction in the link he provided is simple enough to follow.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.