Click here to Skip to main content
Click here to Skip to main content

Toggling the Num Lock, Caps Lock, and Scroll Lock keys

, 24 May 2002 CPOL
Rate this:
Please Sign up or sign in to vote.
How to toggle the Num Lock, Caps Lock, and Scroll Lock keys programmatically.

<!------------------------------- STEP 3 ---------------------------> <!-- Add the article text. Please use simple formatting (

,

etc) -->

Introduction

I have a status bar that toggles the Num Lock, Caps Lock and Scroll Lock keys in one application but some time ago I discovered that the API function SendInput I used for it requires Windows 98 or later and Windows NT 4.0 with Service Pack 3.0 or later. I have browsed MSDN and found that there are 2 more functions that can toggle keyboard state but each of them have some specific limitations like SendInput does. To make it easier for others I have posted all possible variants with their descriptions and limitations and a simple solution for toggling these keys avoiding compatibility problems.

Variant A - using keybd_event

Description:

The keybd_event function synthesizes a keystroke. The system can use such a synthesized keystroke to generate a WM_KEYUP or WM_KEYDOWN message. The keyboard driver's interrupt handler calls the keybd_event function.

Version Computability:

Windows NT/2000/XP: Requires Windows NT 3.1 or later.
Windows 95/98/ME: Requires Windows 95 or later.
Windows CE: Requires version 1.0 or later.

Important Notes:

  1. An application can simulate a press of the PRINTSCRN key in order to obtain a screen snapshot and save it to the clipboard. To do this, call keybd_event with the first parameter set to VK_SNAPSHOT.
  2. Windows 95/98/Me: The keybd_event function can toggle only the CAPS LOCK and SCROLL LOCK keys. It cannot toggle the NUM LOCK key. We can do this with SendInput but it requires Windows NT 4.0 SP3 and later or Windows 98 and later.
  3. Windows NT/2000/XP: The keybd_event function can toggle the NUM LOCK, CAPS LOCK, and SCROLL LOCK keys.

Sample Usage

When setting key state be sure to generate both key press and key release (see below). Notes: Windows NT/2000: This function has been superseded. Use SendInput instead.

//
    // Toggle Caps Lock key:
    ::keybd_event( VK_CAPITAL, 0x45, KEYEVENTF_EXTENDEDKEY, 0 );
    ::keybd_event( VK_CAPITAL, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 );
//

Variant B - using SendInput

Description:

The SendInput function synthesizes keystrokes, mouse motions, and button clicks.

Version Compatibility:

Windows NT/2000/XP: Requires Windows NT 4.0 SP3 or later.
Windows 95/98/Me: Requires Windows 98.
Windows CE: Requires version 2.0 or later.

Sample Usage:

When setting key state be sure to generate both key press and key release (see below). And do not forget to include WinAble.h, not WinUser.h as MSDN says.

//
    #include <WinAble.h> // Required for the ::SendInput function
//...
    // Toggle Caps Lock key:
    INPUT input[2];
    ::ZeroMemory(input, sizeof(input));        
    input[0].type = input[1].type = INPUT_KEYBOARD;
    input[0].ki.wVk  = input[1].ki.wVk = VK_CAPITAL;        
    input[1].ki.dwFlags = KEYEVENTF_KEYUP;  // THIS IS IMPORTANT
    ::SendInput(2, input, sizeof(INPUT));
//

Variant C - using SetKeyboardState

Description:

The SetKeyboardState function copies a 256-byte array of keyboard key states into the calling thread's keyboard-input state table.

Version Compatibility:

Windows NT/2000/XP: Requires Windows NT 3.1 or later.
Windows 95/98/Me: Requires Windows 95 or later.
Windows CE: Unsupported.

Important Notes:

  1. Because the SetKeyboardState function alters the input state of the calling thread and not the global input state of the system, an application cannot use SetKeyboardState to set the NUM LOCK, CAPS LOCK, or SCROLL LOCK indicator lights on the keyboard.
  2. SetKeyboardState function sets keyboard state for calling thread only, not the global input state of the system.

Sample Usage:

//
    // Toggle Caps Lock key:
    BYTE byKeybState[256];
    ::GetKeyboardState(byKeybState);         
    byKeybState[nVirtKey] = !(BOOL)::GetKeyState(VK_CAPITAL);
    ::SetKeyboardState(byKeybState);
//

Support for setting Num Lock, Caps Lock and Scroll Lock Keys State

Function\OS
Win CE 1.0
Win CE 2.0
Win 95
Win 98/Me
Win NT
Win 2000/XP
keybd_event
Yes
Yes
All but Num Lock
All but Num Lock
Yes
Yes
SendInput
 
Yes
 
Yes
SP3*
Yes
SetKeyboardState
 
 
Yes**
Yes**
Yes**
Yes**

* - Requires Service Pack 3 or later.
** - Does not set indicator lights on the keyboard and toggles input state of the calling thread only.

Simple Solution

Sample Image

I have provided a simple StatusBar class that toggles the keys when the appropriate pane is double-clicked. See below:

//
#include <WinAble.h> // Required for the ::SendInput function
//...

void CStatusBarEx::OnNMDblclk(NMHDR* pNMHDR, LRESULT *pResult)
{
    // Get the double-clicked pane index:
    
    NMMOUSE* pNMMOUSE = (NMMOUSE*)pNMHDR;
    INT nInd = GetItemID((int)pNMMOUSE->dwItemSpec);

    if((nInd >= ID_INDICATOR_CAPS) && 
       (nInd <= ID_INDICATOR_OVR))
    {        
        UINT nVirtKey = 0;
        switch(nInd)
        {
        case ID_INDICATOR_CAPS: nVirtKey = VK_CAPITAL; break;
        case ID_INDICATOR_NUM:  nVirtKey = VK_NUMLOCK; break;
        case ID_INDICATOR_SCRL: nVirtKey = VK_SCROLL;  break;
        case ID_INDICATOR_OVR:  nVirtKey = VK_INSERT;  break;
        }
        
        ASSERT(nVirtKey >= 1 && nVirtKey<= 254);
    
        DWORD dwVersion = ::GetVersion();

        // Windows NT/2000/XP: The keybd_event function can toggle the 
        // NUM LOCK, CAPS LOCK, and SCROLL LOCK keys although
        // this function has been superseded by ::SendInput.

        if( dwVersion < 0x80000000) // Win NT
        {            
            ::keybd_event( nVirtKey, 0x45, KEYEVENTF_EXTENDEDKEY, 0 );
            ::keybd_event( nVirtKey, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0 );
        }
        else
        {
            // Windows 95/98/Me: The keybd_event function can toggle only the 
            // CAPS LOCK and SCROLL LOCK keys. It cannot toggle the NUM LOCK key.
            // We can do this with SendInput but it requires 
            // Windows NT 4.0 SP3 and later or Windows 98 and later.

            DWORD dwMin = (DWORD)(HIBYTE(LOWORD(dwVersion)));
            if(dwMin >= 10) // Windows 98 and later
            {
                INPUT input[2];
                ::ZeroMemory(input, sizeof(input));        
                input[0].type = input[1].type = INPUT_KEYBOARD;
                input[0].ki.wVk  = input[1].ki.wVk = nVirtKey;        
                input[1].ki.dwFlags = KEYEVENTF_KEYUP;  // THIS IS IMPORTANT
                ::SendInput(2, input, sizeof(INPUT));
            }
            else // Windows  95
            {
                // Because the SetKeyboardState function alters the input state 
                // of the calling thread and not the global input state of the system, 
                // an application cannot use SetKeyboardState to set the 
                // NUM LOCK, CAPS LOCK, or SCROLL LOCK (or the Japanese KANA) indicator
                // lights on the keyboard.

                BYTE byKeybState[256];
                ::GetKeyboardState(byKeybState);         
                byKeybState[nVirtKey] = !(BOOL)::GetKeyState(nVirtKey);
                ::SetKeyboardState(byKeybState);
            }
        }
        ::Beep(500, 100);
    }
    else
    {
        CWnd* pWnd = GetParent();
        if(pWnd != NULL)
        {             
            //TODO: SendNotifyMessage; 
        }
    }

    *pResult = 0;
}
//

Please send me all bugs, fixes or better solutions.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Armen Hakobyan
Software Developer (Senior) SafeNet Inc
United States United States
No Biography provided

Comments and Discussions

 
-- No messages --
Try changing the 'Date Filter' value
| Advertise | Privacy | Mobile
Web01 | 2.8.141015.1 | Last Updated 25 May 2002
Article Copyright 2002 by Armen Hakobyan
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid