How to Find the State of Numlock, Capslock and Scrolllock in .Net

How can I find the state of NumLock, CapsLock and ScrollLock in .NET?

Import the WinAPI function GetKeyState:

[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)]
public static extern short GetKeyState(int keyCode);

And then you can use it like this:

bool CapsLock = (((ushort)GetKeyState(0x14)) & 0xffff) != 0;
bool NumLock = (((ushort)GetKeyState(0x90)) & 0xffff) != 0;
bool ScrollLock = (((ushort)GetKeyState(0x91)) & 0xffff) != 0;

It is for framework 1.1. For framework 2.0 (and later) you can use:

Control.IsKeyLocked

State of Num Caps ScrollLock in StatusStrip WindowsForms

I solved it:

protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
capsStatusLabel.ForeColor = IsKeyLocked(Keys.CapsLock) ? statusStrip1.ForeColor : statusStrip1.BackColor;
numStatusLabel.ForeColor = IsKeyLocked(Keys.NumLock) ? statusStrip1.ForeColor : statusStrip1.BackColor;
}

Thanks all!

Toggle NUMLOCK / CAPSLOCK / SCROLLLOCK while the workstation is locked?

At least on Windows, it really seems there is no way to toggle these keys when the workstation is locked. No matter what language or framework is in use, they all need to pass through the underlying OS layer. Without an interactive session, these key presses are not sent.

Naturally, if you are standing at the keyboard and pressing these keys, they respond just fine.

So, this CAN be done, by controlling a keyboard as an attached peripheral, such as Arduino. Some of these models can act as a USB keyboard/mouse. (I have tried this using both the Arduino Leonardo and Spark Fun Pro Micro. Both respond the same way for this use case.)

NOTE: even when toggle keys are updated by Arduino or by a person at the terminal, the toggle key states are NOT updated in the operating system until the workstation is unlocked. Whatever state a toggle key has when the workstation is locked, regardless of what the person at the locked terminal does with the keyboard, that key will continue to appear in that state to any running scripts until the moment the workstation is unlocked. This can be easily verified using the AHK script below.


Below is a minimal example of the AutoHotKey control script (although any program that can send data over a serial connection will do just as well), and the Arduino sketch:

AutoHotKey control script

Loop
{
RS232_FileHandle := RS232_Initialize()
if (RS232_FileHandle)
{
; Turn them all off
(1 = GetKeyState("NumLock", "T")) ? RS232_Write(RS232_FileHandle, "219") : NA
Sleep, 750
(1 = GetKeyState("CapsLock", "T")) ? RS232_Write(RS232_FileHandle, "193") : NA
Sleep, 750
(1 = GetKeyState("ScrollLock", "T")) ? RS232_Write(RS232_FileHandle, "207") : NA

Sleep, 4000

; Turn them all on
(0 = GetKeyState("NumLock", "T")) ? RS232_Write(RS232_FileHandle, "219") : NA
Sleep, 750
(0 = GetKeyState("CapsLock", "T")) ? RS232_Write(RS232_FileHandle, "193") : NA
Sleep, 750
(0 = GetKeyState("ScrollLock", "T")) ? RS232_Write(RS232_FileHandle, "207") : NA

RS232_Close(RS232_FileHandle)
}
Sleep, 4000
}

RS232_LoadSettings()
{
RS232_Port := "COM3"
RS232_Baud := "9600"
RS232_Parity := "N"
RS232_DataBits := "8"
RS232_StopBits := "1"
RS232_Timeout := "Off"
RS232_XonXoff := "Off"
RS232_CTS_Hand := "Off"
RS232_DSR_Hand := "Off"
RS232_DSR_Sens := "Off"
RS232_DTR := "Off"
RS232_RTS := "Off"

; MSDN Reference: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/mode
RS232_Settings = %RS232_Port%:BAUD=%RS232_Baud% PARITY=%RS232_Parity% DATA=%RS232_DataBits% STOP=%RS232_StopBits% to=%RS232_Timeout% xon=%RS232_XonXoff% odsr=%RS232_DSR_Hand% octs=%RS232_CTS_Hand% dtr=%RS232_DTR% rts=%RS232_RTS% idsr=%RS232_DSR_Sens%
return RS232_Settings
}

RS232_Initialize()
{
; Source adapted from: https://autohotkey.com/board/topic/26231-serial-com-port-console-script/
RS232_Settings := RS232_LoadSettings()
RS232_Port := StrSplit(RS232_Settings, ":")[1]
RS232_COM := (4 <= StrLen(RS232_Port) ? "\\.\" : "") . RS232_Port
StringTrimLeft, RS232_Settings, RS232_Settings, StrLen(RS232_Port)+1
VarSetCapacity(DCB, 28)
if (1 <> DllCall("BuildCommDCB","str",RS232_Settings,"UInt",&DCB))
{
return false
}
hCom := DllCall("CreateFile","Str",RS232_COM,"UInt",0xC0000000,"UInt",3,"UInt",0,"UInt",3,"UInt",0,"UInt",0,"Cdecl Int")
if (hCom < 1)
{
return false
}
if (1 <> DllCall("SetCommState","UInt",hCom,"UInt",&DCB))
{
RS232_Close(hCom)
return false
}
VarSetCapacity(Data, 20, 0)
NumPut(0xffffffff, Data, 0, "UInt")
NumPut(0x00000000, Data, 4, "UInt")
NumPut(0x00000000, Data, 8, "UInt")
NumPut(0x00000000, Data, 12, "UInt")
NumPut(0x00000000, Data, 16, "UInt")
if (1 <> DllCall("SetCommTimeouts","UInt",hCom,"UInt",&Data))
{
RS232_Close(hCom)
return false
}
return hCom
}

RS232_Write(hCom, msg)
{
SetFormat, Integer, DEC
StringSplit, Byte, msg, `,
Data_Length := Byte0
VarSetCapacity(Data, Byte0, 0xFF)
i := 1
Loop %Byte0%
{
NumPut(Byte%i%, Data, (i-1) , "UChar")
i++
}

Bytes_Sent := 0
WF_Result := DllCall("WriteFile","UInt",hCom,"UInt",&Data,"UInt",Data_Length,"UInt*",Bytes_Sent,"Int","NULL")
if (WF_Result <> 1 or Bytes_Sent <> Data_Length)
{
return false
}
return Bytes_Sent
}

RS232_Close(hCom)
{
return (1 == DllCall("CloseHandle","UInt",hCom))
}

Arduino sketch

/* Pro Micro NumCapsScrollToggleDemo
by: Jonathan David Arndt
date: March 6, 2020

This will allow the toggle of the Num Lock, Caps Lock, and Scroll Lock keys
on the keyboard, via commands sent over USB serial
*/

#include <Keyboard.h>

// You could patch this into your Keyboard.h file, or just define it here
// Source: https://forum.arduino.cc/index.php?topic=173583.0 (attachment: USBAPI.h)
#define KEY_NUM_LOCK 0xDB
#define KEY_SCROLL_LOCK 0xCF

void pressAndRelease(int c);

void setup()
{
Serial.begin(9600); // This pipes to the serial monitor
delay(3000); // Wait a moment for things to get setup
Serial.println("Initialize Serial Monitor");
}

void loop()
{
int c = 0;

if (0 < Serial.available())
{
c = Serial.read();
if (219 == c)
{
pressAndRelease(KEY_NUM_LOCK);
}
else if (193 == c)
{
pressAndRelease(KEY_CAPS_LOCK);
}
else if (207 == c)
{
pressAndRelease(KEY_SCROLL_LOCK);
}
}
}

void pressAndRelease(int c)
{
Keyboard.press(c);
Keyboard.release(c);
}

Get and set Num/Caps/Scroll-lock status in Mono C#

The .NET Console.CapsLock and NumberLock properties return the key state. Mono has them too, but they are not yet documented. Give it a try.

C# Actively detect Lock keys

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);
}

How to detect NumLock on/off status in WPF

Here's my solution:

bool isNumLockedPressed = System.Windows.Input.Keyboard.IsKeyToggled(System.Windows.Input.Key.NumLock);

int numLockStatus { get; set; }

public MainWindow()
{
if (isNumLockedPressed == true)
{
numLockStatus = 1;
NumLock.Foreground = System.Windows.Media.Brushes.White;
}

else
{
numLockStatus = 0;
NumLock.Foreground = System.Windows.Media.Brushes.Red;
}

}

private void NumLockKey_Press(object sender, KeyEventArgs e)
{
if (e.Key == Key.NumLock && e.IsToggled)
{
numLockStatus = 1;
NumLock.Foreground = System.Windows.Media.Brushes.White;
}

else if (e.Key == Key.NumLock && e.IsToggled == false)
{
numLockStatus = 0;
NumLock.Foreground = System.Windows.Media.Brushes.Red;
}
}

Capslock ON & OFF with Application

Take a look at this post for the API for discovering whether caps lock is on or not: -

How can I find the state of NumLock, CapsLock and ScrollLock in .net?

See example for comment: -

AppDomain.CurrentDomain.ProcessExit += new EventHandler(OnExit);

public void OnExit(object sender, EventArgs e)
{
// check and turn caps off if neccessary
}


Related Topics



Leave a reply



Submit