简体   繁体   中英

How do I manually toggle the NumLock Key with C# in WPF?

I've been searching for a while and there are mostly results in C++ or other languages, and not C#. Things I've seen:

   keybd_event() // A c++ method that theoretically can be included with a DLL import, but hasn't worked in testing
   System.Windows.Forms.SendKeys.Send("{NUMLOCK}"}; // Forms namespace doesn't exist in Windows

Currently, I have code that executes every second or so to watch the state of numlock and update a graphic in my form accordingly. If a bool toggle is set, I also want it to force NumLock on:

            bool NumLock = (((ushort)GetKeyState(0x90)) & 0xffff) != 0;
            if (NumLock)
            {
                this.Dispatcher.Invoke(() =>
                {
                    fixerBoxes["NumL"].FixerImg.Source = new BitmapImage(new Uri(@"/graphics/num_lock_on.png", UriKind.Relative));
                });
            }
            else {
                this.Dispatcher.Invoke(() =>
                {
                    fixerBoxes["NumL"].FixerImg.Source = new BitmapImage(new Uri(@"/graphics/num_lock_off.png", UriKind.Relative));
                });
            }

            if (fixers.watchNumL)
            {
                // Force NumLock back on
            }

Here is a class (with a library) that can do this for you. the library does much more, so it's maybe a bit overkill to use just for this. The approach uses the keybd_event function using pinvoke:

// Simulate a key press
Interop.keybd_event((byte)virtualKey,
    0x45,
    Interop.KEYEVENTF_EXTENDEDKEY | 0,
    IntPtr.Zero);

// Simulate a key release
    Interop.keybd_event((byte)virtualKey,
    0x45,
    Interop.KEYEVENTF_EXTENDEDKEY | Interop.KEYEVENTF_KEYUP,
    IntPtr.Zero);

Pressing and releasing the button changes the state of the LED. virtualKey is one of the VK_ constants.

Here are the declarations:

internal partial class Interop
{
    public static int VK_NUMLOCK = 0x90;
    public static int VK_SCROLL = 0x91;
    public static int VK_CAPITAL = 0x14;
    public static int KEYEVENTF_EXTENDEDKEY = 0x0001; // If specified, the scan code was preceded by a prefix byte having the value 0xE0 (224).
    public static int KEYEVENTF_KEYUP = 0x0002; // If specified, the key is being released. If not specified, the key is being depressed.

    [DllImport("User32.dll", SetLastError = true)]
    public static extern void keybd_event(
        byte bVk,
        byte bScan,
        int dwFlags,
        IntPtr dwExtraInfo);

    [DllImport("User32.dll", SetLastError = true)]
    public static extern short GetKeyState(int nVirtKey);

    [DllImport("User32.dll", SetLastError = true)]
    public static extern short GetAsyncKeyState(int vKey);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM