Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Read and Update CAPS or NUM Lock Status from your Application

0.00/5 (No votes)
23 May 2008 1  
It describes how to read and update the toggle keys (NUM lock, CAPS lock, etc.) using WIN32 API in a C# application

Introduction

A few months ago, I was developing a desktop application for a client. After completing the requirements, I was enhancing the UI specially the main form. In the previous versions of Microsoft Word (before version 2007), there are some labels which are clickable and reflect the changes to the keyboard (details below) and I wanted to add these features to my applications.

HTML documentation of the code has also been included along the source in the zip file. Select the index.html in the HTML folder to view it.

Toggle Keys

There are three LEDs on almost every keyboard, i.e. NUM lock, CAPS lock and SCROLL lock. These LEDS shows the status of the respective keys. As these keys are either in ON state or OFF state, their value is toggled between 1 and 0, so these are called Toggle Keys. The INSERT key is also included in toggle keys, although there is no LED for it but its value is either ON (insert mode) or OFF (overwrite mode), so it is also included in this category.

In my application, I wanted to add the status of NUM lock and CAPS lock. I Googled it and got a solution using Microsoft.VisualBasic.Devices. It was a pretty simple solution but with some limitation. You can only read the status of the keys, no method to set the status of the keys. (I am not going to discuss this here, I might write a separate post for it). The application deadline was very close and I was not able to implement this extra feature as I had planned. Since this feature was not requested by the client, it was delivered with read only options.

Objective

The objective of the post is to get and set the CAPS lock and NUM lock, etc. from the application.

Background

WIN32 API provides a lot of low level functions to access the system hardware. Due to high level of security, these features are not directly available in .NET Framework. To perform low level interaction with hardware, we have to call the WIN32 API methods in .NET using some special syntax.

For this purpose, System.Runtime.InteropServices namespace must be included.

Following the C language style, we have to declare the function so that we could use the method in the code.

Declaration

[DllImport("APIname.dll")]
internal static extern returnType 
MethodName (argument(s)); 

Usage

You can use this method as any other local method:

 int nvar = Win32APIMethodName();

WIN32 API Methods Used

Two methods of WIN32 API have been used to achieve the desired results.

[DllImport("user32.dll")] 
internal static extern short GetKeyState(int keyCode);

The GetKeyState method returns the status of the key specified through the key code argument. Return value will be 0 if off and 1 if on.

Parameter

keyCode: Specifies a virtual-key code for the key to be checked. The code must be a value in the range 1 to 254. For a complete list, see Virtual-Key Codes.

Please check MSDN for a complete description.

[DllImport("user32.dll")]
static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);

This function is useful to simulate Key presses to the window with focus.

Parameters

bVk: Specifies a virtual-key code. The code must be a value in the range 1 to 254. For a complete list, see Virtual-Key Codes.

bScan: Specifies a hardware scan code for the key.

dwFlags: Specifies various aspects of function operation. Normally KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP are used. If specified, the key is being released. If not specified, the key is being depressed.

dwExtraInfo: Specifies an additional value associated with the key stroke.

Please check MSDN for complete description.

Note: In the test application, instead of the Virtual key Codes, we will be using System.Keys enumeration where required.

Creating a Test Application

Create a new Windows Application Project in C#. From Menus & Toolbar section of the control box, add a Status Strip on your form. Add three labels to the status strip. Name them as lblINS, lblNUM and lblCAPS respectively. It is better to set their width to 40.

Set the DoubleClickEnabled property of these labels to true.

Set the AutoSize property of these labels to false.

Generate the DoubleClick event for these labels to handle the double click action, e.g.

private void lblNUM_DoubleClick(object sender, EventArgs e)
{
    PressKeyboardButton(Keys.NumLock);
UpdateNUMLock();
}

Form Events

Set the KeyPreview property of the form to true. This will help to pass the keys pressed on the child controls to the parent control (form) (for better understanding of the property, build the attached test application with this property set to false).

In the design view, double click the form to generate its Form_Load event and call the method UpdateKeys. It will read the current status of the keys and update the form accordingly.

private void Form1_Load(object sender, EventArgs e)
{
    // read the current status of the specified keys
    UpdateKeys();
}

Generate the Form1_KeyUp event of the form to handle the key press event (this event is raised when a key is pressed and then released).

private void Form1_KeyUp(object sender, KeyEventArgs e)
{            
    if (e.KeyData == Keys.Insert)
    {
        UpdateInsert();
    }
    else if (e.KeyData == Keys.NumLock)
    {
        UpdateNUMLock();
    }
    else if (e.KeyData == Keys.CapsLock)
    {
        UpdateCAPSLock();
    }            
}

Utility Methods

PressKeyboardButton

This method takes the key code as parameter and simulates a key press event by sending a Key-Down message to the operating system followed by a Key-Up message.

private void PressKeyboardButton(Keys keyCode)
{
    const int KEYEVENTF_EXTENDEDKEY = 0x1;
    const int KEYEVENTF_KEYUP = 0x2;
 
    keybd_event((byte)keyCode, 0x45, KEYEVENTF_EXTENDEDKEY, 0);
    keybd_event((byte)keyCode, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
}   
UpdateNUMLock

It reads the status of the NUM lock using GetKeyState and updates the form accordingly.

this.Refresh() has been called at the end to ensure the form update by sending a Redraw request.

private void UpdateNUMLock()
{
    bool NumLock = (GetKeyState((int)Keys.NumLock)) != 0;
  
    if (NumLock)
    {
         lblNUM.Text = "NUM";
    }
    else
    {
         lblNUM.Text = String.Empty;
    }
 
    this.Refresh();
}      

Similarly, the other methods for CAPS lock and INSERT can also be implemented.

Conclusion

Your application will be able to reflect the status of the toggle keys. Also you can update the status of these keys from your application by double clicking the labels in the status strip.

Although I have been reading the articles and blogs for a long time, now I decided to make my contribution by sharing my knowledge and experience. I would love to get your feedback on this and do not forget to rate the post if you like it.

History

  • 2008/05/24 1.0.0.0 First release

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here