Is the CAPS LOCK on?

by Michael S. Kaplan, published on 2006/03/29 03:01 -05:00, original URI: http://blogs.msdn.com/b/michkap/archive/2006/03/29/562606.aspx


A few days ago, Mohammed asked:

I am using System.Windows.Forms.SendKeys to send some keystrokes to the active application. When the CAPS lock on the hosting keyboard is turned on, all my keystrokes get sent with the opposite case, which is an acceptable behavior (SendKeys is dependant on the state of the keyboard).

To work around this issue, I’m trying to detect the state of the CAPS lock key to account for case changes. Does anyone know a way to do this using a .NET library call? I’m using C#.

Thanks,

There is unfortunately nothing built in, which is not to say there shouldn't be!

The trick is to use the GetKeyState function in the Win32 API, which has the following info about its return value:

The return value specifies the status of the specified virtual key, as follows:

That first half may sound familiar to those who read Getting all you can out of a keyboard layout, Part #5, since I used it to give information on whether the shift keys were pressed or not.

Well, the second half is what we're dealing with now -- the low order bit must be set to indicate a toggle key like CAPS LOCK has been pressed. So, you can use code something like this:

[DllImport("user32.dll", ExactSpelling=true)]
internal static extern ushort GetKeyState(uint nVirtKey);

internal const byte VK_CAPITAL      = 0x14;

if(0 != (GetKeyState(VK_CAPITAL) & 1))
{
    // do whatever here
}

(You may remember that I hate the Keys enumeration, as I pointed out in Part 0; also, I did not know about VB.Net's My.Computer.Keyboard.CapsLock but luckily Sara Ford was nearby to point this out for those who are using VB and wanted avoid the const definition!)

And there you have it -- how to find out if the CAPS LOCK is toggled.

As I am sure you can imagine, we're going to be making use of this in a future post in the series. :-)

 

This post brought to you by "Ŧ" (U+0166, a.k.a. LATIN CAPITAL LETTER T WITH STROKE)


# Anonymous on 29 Mar 2006 7:10 AM:

Maybe you should mention that using SendKeys is VERY rarely the right approach. If there really is no programming interface for an application, enumerating its windows and sending messages directly to them is usually a better choice.

# Michael S. Kaplan on 29 Mar 2006 10:46 AM:

Well, the problems you refer to about SendKeys are not really internationalization issues, so it would not be for me to say in this blog. :-)

But never fear, I'll be getting to the problems with SendKeys from an internationalization standpoint eventually. When I do, the other things may get mentioned in passing....

# Mihai on 30 Mar 2006 12:36 AM:

In fact, there is no good solution to "automate" an application withouy a programming interface.

The problem is finding the right window. Enumerating is fine, but there is nothing to say "this is the window I am looking for" in a language-independent manner. One only has access to the window class (and that is the same for most dialogs) and the window text (which changes in localized versions).

Sending messages or SendKey, it does not matter, if you cannoy properly identify the target window.

# Luke Ogg on 20 May 2006 2:31 PM:

I ran across this method in the Framework 2.0:

public static bool IsKeyLocked (
   Keys keyVal
)

Using the following will determine if the caps lock is on:

Control.IsKeyLocked(Keys.CapsLock)

# Michael S. Kaplan on 20 May 2006 3:09 PM:

Hi Luke,

Interesting! I had not seen this one before....

I've been working hard to try and make sure the code works with either 1.1 or 2.0 (or even unmanaged techniques), but I will applaud new stuff that makes it easier for people!

# Ray Woods on 7 Jun 2006 10:22 PM:

The information was excellent.  I have it bookmarked.

Thanks!!!!!!!!!!!!!!!!

# Caio Proiete on 18 Mar 2008 12:23 PM:

Wouldn't be easier to just use the CapsLock property of the Console class?

if (Console.CapsLock)

{

   // Caps Lock is on...

}

Cheers,

Caio Proiete

# Michael S. Kaplan on 18 Mar 2008 12:30 PM:

In a non-Console app? That kind of thing makes me nervous if it is not either documented as supported (or at least I've had a chance to look at the code behind the implementation!)....

Beyond all that and most significantly

a) there is the fact that it doesn't exist in .Net 1.0/1.1 (the pinvoke solution works in any version)

b) this technique will work for any toggle key. including ones that have no property available.


referenced by

2006/04/10 Getting all you can out of a keyboard layout, Part #8

go to newer or older post, or back to index or month or day