Getting and Monitoring Caps Lock Status

How can I display the the current status of the CAPS LOCK key in my application?


There are several ways to address this, and one I have seen before is to check the KeyPress event, and modify the status according to each press of the CapsLock key.   The problem with this approach is that it would not give you the necessary status at the time the application started. We therefore have to get our hands dirty to get the ideal solution, and dig into the Windows API. Luckily, the code is quite simple.

We use the GetKeyState function, passing it the CapsLock key constant and receiving a return value. If the return value is zero, CapsLock is off, otherwise it is on. Simple code then, dropped into a button click event:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
   if GetKeyState(VK_CAPITAL) > 0 then 
     Label1.Caption := 'Caps Lock On'
   else 
     Label1.Caption := 'Caps Lock Off'; 
end; 

Naturally this could easily be modified into a usable function to return the value so that it could be used by more than one routine and avoid code duplication. Firstly, modify it to return the integer status:

function GetCapsLockStatus: Integer; 
begin 
   Result := GetKeyState(VK_CAPITAL); 
end; 

You would call this from wherever you wanted, and one possible use would achieve the same thing as the original code:

procedure TForm1.Button1Click(Sender: TObject); 
begin 
   if GetCapsLockStatus > 0 then 
     Label1.Caption := 'Caps Lock On' 
   else 
     Label1.Caption := 'Caps Lock Off'; 
end; 

You could also convert it to a function that returns a string:

function GetCapsLockStatusString: Integer; 
begin 
   if GetCapsLockStatus > 0 then 
     Result := 'On' 
   else 
     Result := 'Off'; 
end; 

Usage of this would be simple, assigning the resulting string directly to a label caption:

procedure TForm1.Button2Click(Sender: TObject); 
begin 
   Label1.Caption := GetCapsLockStatusString; 
end; 

Once you have the original status you can either monitor keypresses for the CapsLock key (check for the virtual key constant VK_CAPITAL) and change the caption appropriately, or simply insert the call into a routine that is regularly called.  Note that inserting the function call into the OnKeyPress event would work, but there would be consequences in the performance hit caused by the function running and the label being rewritten every time any key is pressed.

There we go then - simple but effective use of the Windows API to achieve the desired result.

Chris Bray
Vertical Software 2004, all rights reserved.