2

I have a wireless keyboard and mouse that doesn't have any lock indicators, nor any software bundled to provide a visual aid, so I'm making my own.

I got it so that if I click on a notifyIcon it'll list which lock(s) are turned on, but I'd like to make it smarter by alerting me once the locks are engaged.

I found a few items online, but honestly I just want the lock keys, I don't care about any other keyboard presses.

I'm using C# .NET 4, though I can use .NET 4.5 if there's something with that version.

Thanks.

Eman
  • 1,093
  • 2
  • 26
  • 49

4 Answers4

3

You will want to register some sort of keyboard hook to listen for the key presses and then retrieve the state of the lock keys like this:
http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx

In addition to the above article, make the below modifications to capture state of the lock keys:

private static IntPtr HookCallback(
    int nCode, IntPtr wParam, IntPtr lParam)
{
    if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
    {
        int vkCode = Marshal.ReadInt32(lParam);
        Keys key = (Keys)vkCode;
        if (key == Keys.Capital)
        {
            Console.WriteLine("Caps Lock: " + !Control.IsKeyLocked(Keys.CapsLock)); 
        }
        if (key == Keys.NumLock)
        {
            Console.WriteLine("NumLock: " + !Control.IsKeyLocked(Keys.NumLock));
        }
        if (key == Keys.Scroll)
        {
            Console.WriteLine("Scroll Lock: " + !Control.IsKeyLocked(Keys.Scroll));
        }
        Console.WriteLine((Keys)vkCode);
    }
    return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
Cameron Tinker
  • 9,634
  • 10
  • 46
  • 85
  • how could i use it as a non-console app? – Eman Jul 16 '13 at 19:50
  • In each of the `if` statements, you could display a balloon tip by using a NotifyIcon control to display keyboard state changes. http://msdn.microsoft.com/en-us/library/system.windows.forms.notifyicon.aspx – Cameron Tinker Jul 16 '13 at 20:03
  • 3
    Don't recommend that Toub article anymore, it has a [critical bug](http://stackoverflow.com/a/3684292/17034) that stops it from working in .NET 4. – Hans Passant Jul 16 '13 at 20:46
  • Thanks guys for your help, this solution was what helped me get the application to work like I want. – Eman Jul 17 '13 at 12:56
2

Here is an example for intercepting the keyup on a form or something and tracking it. I changed a local variable, but you can just as easily trigger GUI updates at that time.

    private bool capLock;
    private bool numLock;
    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.CapsLock)
        {
            capLock = !capLock;
        }
        if (e.KeyCode == Keys.NumLock)
        {
            numLock = !numLock;
        }
    }
Ted
  • 3,212
  • 25
  • 20
0

Look at the following article on global keyboard events. When one of the locks keys is pressed you could update your UI...

http://www.codeproject.com/Articles/7294/Processing-Global-Mouse-and-Keyboard-Hooks-in-C

dazedandconfused
  • 3,131
  • 1
  • 18
  • 29
  • While links to articles are great, links break. Please include the relevant information in your answer. http://meta.stackexchange.com/questions/8231/are-answers-that-just-contain-links-elsewhere-really-good-answers – cadrell0 Jul 16 '13 at 18:04
0

You can use Control.IsKeyLocked(...) method as described here: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.iskeylocked%28v=vs.100%29.aspx.

The method is available since .NET 2.0 and can be used like this:

bool capsLock = Control.IsKeyLocked(Keys.CapsLock);
bool numLock = Control.IsKeyLocked(Keys.NumLock);
bool scrollLock = Control.IsKeyLocked(Keys.Scroll);

This solution doesn't require importing WinApi functions or manually tracking keys states.

Update

In order to track changes of the lock keys, I can suggest You to try one of those solutions:

  • Adding a global hook to catch all key presses and then check if the key pressed was one of the lock keys. This would, however, make Your hook run each time any key is pressed. You can find more information about global hooks for keyboard keys here: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx.
  • You can also implement a timer executing once in a while, check the key states and inform the user, if state of any of them was changed. If You don't run the timer too often, it shouldn't take much resources.
Lukasz M
  • 5,635
  • 2
  • 22
  • 29
  • I'm already using that method, the issue how to notify the user of it without any extra interaction. – Eman Jul 16 '13 at 18:06
  • 2
    I suppose You'll have to add a global hook if You want to catch all key presses, even if You app is not currently in the foreground. Take a look at this for more information: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx. – Lukasz M Jul 16 '13 at 18:10