I'm trying to find a way to intercept and block the CapsLock
toggle event globally with WinAPI.
I have tried using SetWindowsHookEx
with WH_KEYBOARD_LL
and checking for WPARAM==WM_KEYDOWN || WPARAM==WM_SYSKEYDOWN
messages, and LPARAM->vkCode==VK_CAPITAL || LPARAM->scanCode==0x3A
, but this results in me intercepting/blocking CapsLock
when it's held down/pressed, not only when it's actually toggled.
The reason it's important to me that it only intercepts the toggled event is because certain software (like screen readers) can use a single press or holding of CapsLock
as a modifier, which is not something I wish to disrupt.
I'm currently using GetKeyState(VK_CAPITAL)&1
to check for capslock getting toggled and forcing it back off by sending CapsLock
with SendInput
, but I would rather intercept/block it if any possible.
Is there any way to hook into whatever GetKeyState(VK_CAPITAL)&1
does or intercept/block something like wm_toggle message before other things can receive it?
CodePudding user response:
Use GetAsyncKeyState to detect when/if the caps key is hit, and its current state. Then call keybd_event to programmatically set the caps key back to the state that you want it to be.
The following code snippet (along with other setup code) is included in this link, and will toggle CAPS lock on or off when executed:
RUN keybd_event ({&VK_CAPITAL}, 0, {&KEYEVENTF_KEYUP}, 0, OUTPUT intResult).
RUN keybd_event ({&VK_CAPITAL}, 0, {&KEYEVENTF_EXTENDEDKEY}, 0, OUTPUT intResult).
RUN keybd_event ({&VK_SHIFT}, 0, {&KEYEVENTF_KEYUP}, 0, OUTPUT intResult).
RUN keybd_event ({&VK_SHIFT}, 0, {&KEYEVENTF_EXTENDEDKEY}, 0, OUTPUT intResult).
The recommended way to deploy this implementation (GetAsyncKeyState
/ keybd_event
combination) within your application is to encapsulate it into a worker thread set in a forever loop with sleep()
set to allow sampling of the state approximately every 100ms.
(Note, I believe GetAsyncKeyState()
over GetKeyState()
is an improvement for what you want to do here as GetKeyState()
gets the key status returned from the thread's message queue. The status does not reflect the
interrupt-level state associated with the hardware. GetAsyncKeyState()
specifies whether the key was pressed since the last call to
GetAsyncKeyState()
, and whether the key is currently up or down.)
CodePudding user response:
You could set a low-level hook with SetWindowsHookEx. Refer to the thread: Best way to intercept pressing of Caps Lock