A: 

As you said there's a delay, I am under the impression that you want to decrease the delay, why not call the 'SystemParametersInfo' to set the typematic delay and speed rate, you would need to look at the keyboard delay..'SPI_GETKEYBOARDDELAY' and keyboard speed 'SPI_GETKEYBOARDSPEED'. The function would look like this:

int SetKeyboardSpeed(int nDelay){
   /* fastest nDelay = 31, slowest nDelay = 0 */
   return (SystemParametersInfo(SPI_SETKEYBOARDSPEED, nDelay, NULL, SPIF_SENDCHANGE) > 0);
}
int SetKeyboardDelay(int nDelay){
   /* 0 = shortest (approx 250ms) to 3 longest (approx 1sec) */
   return (SystemParametersInfo(SPI_SETKEYBOARDDELAY, nDelay, NULL, SPIIF_SENDCHANGE) > 0);
}

Edit: In response to Blindy's comment for the downvote - You are 100% correct - Never realized that as I typed the code into this...and yes, you've put a finger on it, Never ever change global/system-wide settings without the user ever knowing about! I stand corrected by Blindy's comment. Please disregard my answer as it is 100% wrong!

Hope this helps, Best regards, Tom.

tommieb75
-1, your app doesn't own the computer, it can't just go changing a user's system settings.
Blindy
@Blindy - please see my amended answer! Thanks for the heads up! :) +1 for your comment from me...which effectively cancels out!!! :) lol
tommieb75
+1  A: 

The presented solution is the right way to do it -- ignore autorepeat, and just record down/up states.

To handle the task switching problem, look into the WM_ACTIVATE message -- it lets one detect when a window loses focus. When this happens to the relevant window, assume all keys become released. (This is similar to what one would have to do with DirectInput when using the nonexclusive cooperative level.)

brone
+2  A: 

You can use GetKeyboardState instead. What you generally want is two arrays; one stores the previous frames' input state, and one stores the current. This allows things like differentiating between being held and being triggered.

// note, cannot use bool because of specialization
std::vector<unsigned char> previous(256);
std::vector<unsigned char> current(256);

// in update_keys or similar:
current.swap(previous); // constant time, yay
GetKeyboardState(&current[0]); // normally do error checking

And you're done.

GMan
Great! I missed this function. So, a curiosity - I keep hearing that "directInput really uses RawInput functions" - is this as fast as DirectInput, and does DirectInput actually end up using this function when you use GetDeviceState()?
bobobobo
@bobobobo: In honesty, I cannot tell you the performance comparisons. I have used all three (this, `GetAsyncKeyState`, and DirectInput), but have never profiled against them. Input takes so little time, it's probably not something to worry about. That said, I'd guess DirectInput did something extremely similar to this (it mostly delegated to Win32, if I recall). This may be faster than `GetAsyncKeyState`, though I suspect `GetAKS` may actually just peek to a certain index in the array that `GetKeyboardState` is copying for us. That is to say, with `GetAKS`, we'd be looping to get a status,
GMan
while `GeytKS` would be moving that look into a `memcpy`. So this should be slightly faster than `GetAKS`. This is all speculation, though; to really know you'd have to profile.
GMan
A: 
  1. use Window messages to detect keypresses, and track the array of pressed keys yourself.
  2. watch for the WM_ACTIVATE message and use GetAsyncKeyboardState at that point to 'fix' the array to match the actual state.

That combination should keep things consistent.

Kylotan