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
How to Use Httpclient to Send Content in Body of Get Request
Why Does C# (4.0) Not Allow Co- and Contravariance in Generic Class Types
How to Wait for Async Method to Complete
Distinct in Linq Based on Only One Field of the Table
How to Monitor Clipboard Content Changes in C#
How to Extract Text from Ms Office Documents in C#
Azure Ad B2C - Role Management
How to Perform a Unicode Aware Character by Character Comparison
How to Downgrade from Visual Studio 2012 Project to Visual Studio 2008
What's the Best Strategy for Equals and Gethashcode
How to Execute Task in the Wpf Background While Able to Provide Report and Allow Cancellation
How to Create CSV Excel File C#
Httpwebrequest Is Extremely Slow!
Detecting Network Connection Speed and Bandwidth Usage in C#
How to Get a Variable's Name as It Was Physically Typed in Its Declaration
Command to Close an Application of Console
Graphics.Drawstring VS Textrenderer.Drawtextwhich Can Deliver Better Quality