What is the fastest way to determine a key press and key holding in Win32? - c++

What is the fastest way to determine a key press and also how to determine if a key is being held? It appears that window messaging is slow. Please provide an example of how to do so, and why it is faster than an alternative.
To be clear, this for a real time loop (a simulation) so I am looking for the fastest way to determine if a key has been pressed and also to check to see if it is being held.

GetAsyncKeyState() is what you're looking for. It reads the physical state of the keyboard, regardless of the input queue state. If the high-bit is set, then the key was down at the time of the call.
// Fetch tab key state.
SHORT tabKeyState = GetAsyncKeyState( VK_TAB );
// Test high bit - if set, key was down when GetAsyncKeyState was called.
if( ( 1 << 15 ) & tabKeyState )
{
// TAB key down...
}
Also, for the record, Windows is not a real-time operating system. If your application requires real-time precision, you may want to select another platform.

If you just want to poll the keyboard state so as to discover which keys are up/down as well as the shift/alt/ctrl state, just call GetKeyboardState (MSDN reference).
When I worked in a game studio, this is exactly how we got keyboard state for each frame. Should be applicable to your simulation code.

TL;DR: you can use GetAsyncKeyState for checking if a key is currently down, but for best application responsiveness to key presses and releases, you want to use the Win32 pipeline code near the bottom of my post.
GetAsyncKeyState works perfectly fine for determining if a key is currently down, but in terms of determining whether a key was first pressed or released and how many times this was done, GetAsyncKeyState misses keystrokes in a CPU-intensive application, even after storing the previous key state.
This was what I tried:
static const unsigned int NumberOfKeys = 256U;
bool previousKeyboardState[NumberOfKeys];
//Get the current state of each key as the application starts to ensure that keys held down beforehand are not processed as pressed keys.
for (unsigned int keyNum = 0U; keyNum < NumberOfKeys; ++keyNum)
{
previousKeyboardState[keyNum] = isKeyDown(keyNum);
}
//Works fine.
bool isKeyDown(int key)
{
return (GetAsyncKeyState(key) & (1 << 16));
}
//Misses key presses when application is bogged down.
bool isKeyFirstPressed(int key)
{
bool previousState = previousKeyboardState[key];
previousKeyboardState[key] = isKeyDown(key);
return (previousKeyboardState[key] && !previousState);
}
//Misses key releases when application is bogged down.
bool isKeyFirstReleased(int key)
{
bool previousState = previousKeyboardState[key];
previousKeyboardState[key] = isKeyDown(key);
return (!previousKeyboardState[key] && previousState);
}
//Example usage:
if (isKeyDown(VK_W))
{
//W key.
}
if (isKeyFirstReleased(VK_SNAPSHOT))
{
//Print screen.
}
GetKeyboardState is no good either, as it does not keep track of the number of key presses or releases. As Erik Philips said in his answer, these are unbuffered solutions, which are no good if you are e.g. writing a game. You would have to process all keystrokes faster than they are received.
Now, my code above works decently well, and may be suitable for many people, but I much prefer not to miss a single keystroke. I hate using applications that are unresponsive. I think the best solution for Win32 applications is to catch WM_KEYDOWN and WM_KEYUP messages in the pipeline and process them. What's nice is that WM_KEYDOWN also provides an auto-repeat count, which could be useful for applications that support entering text (e.g. chat, IDE's, etc.). This also adds a slight complication, which is mentioned in the WM_KEYDOWN documentation:
Because of the autorepeat feature, more than one WM_KEYDOWN message
may be posted before a WM_KEYUP message is posted. The previous key
state (bit 30) can be used to determine whether the WM_KEYDOWN message
indicates the first down transition or a repeated down transition.
There are also Windows keyboard hooks you could look into, but those are more difficult to use. They're good for receiving global key presses though.

Considering that all inter-windows communications are through windows messaging (keyboard events, mouse events, pretty much all events you can imagine), there isn't a lower level way to access the keyboard events (unless you write your own keyboard driver) that I know of.
DirectX still uses the windows keyboard messaging to provide DirectX programmers easier access to keyboard events.
Updated
My note about DirectX was not to use it, but that when Microsoft wanted to make an interface for programmers to use for real time games, they still wrote DirectX on top of the Windows Message Queue.
I would suggest taking a look at how to write a program that can read directly from the message queue. I believe there is a good example Code Project Windows Message Handling - Part 1.
Your two options are to either read from the message queue (buffered) or read directly from the keyboard state (as Bukes states) which means your own loop could techinically miss a keyboard event for any number of reasons.

Related

Efficient Perpetual Numlock Keystate Check

I bought a really nice keyboard (logitech G915) that for whatever inane reason doesn't have a numlock indicator. Thus, I'm using Logitech's lighting SDK to make the functionality myself using the key's rgb backlight.
I have an extremely simple console proof of concept that works:
while (true)
{
if (GetKeyState(VK_NUMLOCK) & 0x1)
LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName::NUM_LOCK, 0, 100, 100);
else
LogiLedSetLightingForKeyWithKeyName(LogiLed::KeyName::NUM_LOCK, 0, 0, 0);
}
But I don't think it's good to eat up cpu cycles with a perpetual while loop for such a tiny feature. Should I just have it sleep for time (length suggested?) or is there a way to sleep until the system gets a numlock state change or am I simply going about this wrong?
Additionally, I haven't looked into it yet, but I want to make this a background process or a tray application (doesn't matter, just hidden away) so I guess answers should have that limitation in mind if it is one.
Thanks!
At app startup, use GetAsyncKeyState() instead of GetKeyState() to get the key's current state and update the light accordingly.
Then, use SetWindowsHookEx() to install a global WH_KEYBOARD_LL hook to detect whenever the key is pressed afterwards. On each callback event, use the state information provided by the hook, or start an asynchronous task to get the current key state immediately after your hook callback exits (as GetAsyncKeyState() has not been updated yet when the callback is called), and then update the light accordingly.
Alternatively, use the Raw Input API to monitor the keyboard and receive WM_INPUT window messages on each key press. And then get the key's current state and update the light accordingly.

What is the difference about GetKeyState and GetAsyncKeyState?

From MSDN , I have learned that GetKeyState is associated with message queue of current thread.
Then I created two sample applications : KeyPresser and BackChecker.
I press a key in KeyPresser , in this application , I am using GetKeyState/GetAsyncKeyState/GetKeyboardState to retrieve the pressed key state , and they tell me that key is pressing down.
Then I send(or post) a message form KeyPresser to BackChecker , to notify BackChecker to check the key state in it's thread .
I get same result from BackChecker indicate that key is pressed. But I think GetKeyState/GetKeyboardState should return zero because the key is pressed in thread of KeyPresser , which is not associated with thread of BackChecker.
Why?
Keyboard input on Windows is buffered. It ensures the user can keep typing, even if the program is temporarily unresponsive. It always is, to some degree, no loss of keystrokes that way. They are added to the message queue, the program's message loop retrieves them with GetMessage() later.
Along with the keystroke, it also stores the state of all the other keys. To ensure that, when the message is eventually retrieved, you can reliable tell what other keys were down. Very important for the modifier keys for example. A shortcut keystroke like Ctrl+A would not work reliably otherwise.
So you generally always use GetKeyState(), you get the state of the keys as they were recorded originally. Or GetKeyboardState(), you get the whole enchilada. Using GetAsyncKeyState() is much less common, it doesn't rely on the buffered state, only needed if the app has very unusual message handling. Might be appropriate in a game perhaps.

How can I detect if any key is pressed by the user in C++ (console)?

I am writing a C++ CLI application how can I detect if any key is pressed by the user. I've seen that in c# but how can it be implement in c++
while(1)
{
while(/* code to check if any key is pressed*/)
{ //rest of the code
// sleep function
}
}
Hint: like in CLI games to move or to take certain action when a key is pressed or don't do any thing if no input is given.
On windows at least you could use GetKeyState
we can use _kbhit() function in c++. _kbhit is equal to 1 if any key is pressed. You have to clear the _kbhit buffer else it will remain 1. Method for clearing is character = getch(); This will save the last entered key in character which you can compare and decide which action to perform on which key.
While loop can be CPU consuming, i do not advice busy waiting method, instead you should think of event hooking.
Here you can read about winapi keystroke event hooking C++ Win32 keyboard events
If you are still interested to use the while loop, you should also free some resources by sleeping after checking that a condition is false (e.g. nanosleep )

Down arrow key of my laptop?

The down arrow key of my laptop is very loose and it does not seems to last very long.
Is it possible to write any programm(in any language but especially C++) hat simulates the down arrow key.say I made a programm such that when I press A,B,C on the key board it simulates down arrow key.
If not then,
Is there any software available to do this?
Use the On-screen keyboard
If you want to simulate input, use the SendInput API. This injects input at a fairly low level, windows automatically routes it to the appropriate thread based on who has focus. Call it twice, once to send the key down, and again to send the key up.
Perhaps the easiest thing to do is to write a simple app that calls RegisterHotkey for some combination like ctrl-alt-Z, and then calls SendInput for a keypress then keyrelease of the down arrow key.
You might need to wait a short time after receiving WM_HOTKEY to give you time to release the set of hotkeys so that the down arrow gets processed alone without those modifiers from your hotkey interfering with it. (...otherwise the focused app might think you typed in shift+alt+downarrow instead of plain downarrow!)
if you're using linux, xmodmap: http://www.xfree86.org/4.2.0/xmodmap.1.html
I think that you are actually looking for Sharpkeys www.randyrants.com/sharpkeys/
This works with the windows registry and can be used to change mappings of keys.
You can easily write a program that sends WM_KEYDOWN and WM_KEYUP messages to the window which has the current focus. Once you have this program, bind it to a function key in the properties for the .exe file.

Change speed of keystroke C++

Basically, when one types, a keydown event happens. If the key is held for more than a certain time (~1 sec) then the key is repeatedly pressed until keyup hapens. I would like to change the time it takes for the key to be automatically repressed in my c++ application. How can this be done?
Thanks
The speed at which a keypress becomes automatically recurring is controlled by Windows.
If you want to manipulate automatic recurrences of key-presses, it might be more advantageous to poll for the state of the key rather than waiting for the keydown event. It depends on how responsive you need your application to be.
This article may help you in figuring out how to query for key states: link
You can use the SystemParametersInfo function to change the keyboard delay and refresh rate, as described in this newsgroup thread.
A simple way to handle this is to establish a buffer of time around the OnKeyDown event. Setup a timer that determines whether control passes to a secondary event handler. If the timer has expired, then it is OK to pass control. If the timer hasn't expired, then you should return and leave the event unhandled. Start the timer right before passing control to your secondary event handler.
void KeyDownHandler(...)
{
// ...
if (TimeLeft() <= 0)
{
StartTimer();
handleKeyDown();
}
}
A timer is better than counting duplicate events because you can't assume that a given system will have the same repeat rate set as yours.
I agree with Stuart that polling for the state of the key might work better. It depends upon what you are trying to accomplish.
Also note that this type of behavior might be highly annoying to your user - why do you need to ignore duplicates?
You might be able to tap into a Windows API but this might be controlled by the OS. Not sure...
You might need to manually draw a command such as to simulate a key press multiple times after a set number of seconds after the key has been pressed.
Use SetKeySpeed api (Kernel)