The two key-state functions in the WIndows API, GetKeyState()
and GetAsyncKeyState()
, both determine key state based on key up/down messages rather than the physical state of the key.
I am working on a program which manipulates input, using SendInput()
, to release modifier keys (alt, ctrl, etc...), send input, and then re-press the modifier keys.
The problem is that I don't know if the modifier keys are still pressed after the input is sent because I have sent the key-up event and both of the above mentioned functions return that the key is up regardless of the state of the physical key. So if I assume they are still down, the user is left with a dangling ctrl-down causing problems until the user presses and releases cntl again (or any modifier key). Otherwise the key may be left up even when the physical key is still down.
So is there any way (preferably without anything too low level) to detect the physical key state. Windows-only methods are fine. Key monitoring (listening for key up events) really isn't possible (or at least really, really not preferable).
You are getting a bit confused here. In fact
GetAsyncKeyState()
does return the key state at the instant thatGetAsyncKeyState()
was called. On the other hand,GetKeyState()
returns the key state based on the history of queued messages.You aren't giving the window manager enough time to process the input you just injected. Until it reaches the "update key states for
GetAsyncKeyState
" part of the code,GetAsyncKeyState
will report the old value. (In particular, it won't reach that point until all low-level keyboard hooks have had a chance to inspect the action and possibly reject it.)In other words, your code has a race condition, and that is what you are observing.
After much testing, I seem to have figured it out. MSDN states about
GetKeyState()
:GetAsyncKeyState()
still works on key up/down messages (not physical key state) however, it just doesn't wait for the message to be read. So if a key event message is sent viaSendInput()
, it will still return incorrectly - in fact, it will be incorrect beforeGetKeyState()
because it will be incorrect immediately after the call.A simple test to demonstrate this functionality is here (VS2010 solution) or just the source here.