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.
asked Dec 27, 2011 at 0:40 judeclarke judeclarke 1,106 5 5 gold badges 17 17 silver badges 31 31 bronze badges"It appears that window messaging is slow." Really? This is difficult to determine since it is impossible for the program to compute the delay between the time where the user pressed the key and the time where the window message was processed. Is this from hearsay of have you somehow measured it to be too slow?
Commented Dec 27, 2011 at 0:45I have measured it in real time loops, it typically takes a few ticks to kick in. And I have also heard it plenty of times over the last few years.
Commented Dec 27, 2011 at 0:47I have some experience with non-interactive real-time systems and extensive experience with the Win32 API. I also have a lot of experience helping people on StackOverflow. A piece of advice: don't make broad and vague unjustified claims or use subjective terms if you expect a complete answer. Be explicit. In this case, a detailed explanation of your tests and how fast/slow they are would be a great help.
Commented Dec 27, 2011 at 1:10I am not trying to be argumentative, however, the message loop for input is known for being slower than its counter parts (such as GetKeyState), I would dare say it is one of the most basic things you learn first with windows input programming.
Commented Dec 27, 2011 at 1:21@judeclarke Downvoting a question is not necessarily abusive. If you think the downvote is justified, try to learn from it and keep an open mind. Otherwise don't worry about it. It's only -2 rep and you'll get it back in no time by asking more quality questions and providing great answers. That said, if you want to report someone's behaviour flagging for moderator attention is the way to go. Keep in mind, though, that there's nothing we can do about downvotes on a specific post. I'll clean up the comments on this post and hopefully that'll be enough for now.
Commented Dec 27, 2011 at 6:09GetAsyncKeyState() 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
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.
answered Dec 27, 2011 at 0:53 3,708 1 1 gold badge 19 19 silver badges 20 20 bronze badges Can you please provide an example of its usage? Commented Dec 27, 2011 at 0:53 Updated with sample, as requested. Commented Dec 27, 2011 at 1:11After doing numerous tests, it appears this is exactly what I was looking for. This is definitely more responsive than simple window messaging works great. Thank you for the help.
Commented Dec 27, 2011 at 5:56This works excellently for checking the current state of the key, but it misses key strokes when checking for key presses and releases. See my answer for more info.
Commented May 19, 2015 at 0:14 Um. test high bit would be if ( ( 1 << 15 ) & tabKetState ) Commented Mar 13, 2017 at 22:43If 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.
37.1k 15 15 gold badges 113 113 silver badges 150 150 bronze badges answered Dec 27, 2011 at 0:53 104k 15 15 gold badges 106 106 silver badges 181 181 bronze badgesUpdate. I'm likely going to downvote my own answer in favor of @Bukes response below. According to MSDN for GetKeyboardState: An application can call this function to retrieve the current status of all the virtual keys. The status changes as a thread removes keyboard messages from its message queue. The status does not change as keyboard messages are posted to or retrieved from message queues of other threads.
Commented Dec 27, 2011 at 3:54With the above in mind, if you are pumping messages (GetMessage and DispatchMessage on each frame of your simulation, then you might be OK to use GetKeyboardState. Otherwise, GetAsyncKeyState.
Commented Dec 27, 2011 at 3:55Thank you for the help, I was pumping messages on each frame. I ended up picking Bukes answer, but you were definitely helpful (so I upvoted, as yours is also a very likely scenerio for someone else possibly).
Commented Dec 27, 2011 at 5:58TL;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 //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.