GetAsyncKeyState

1
2
3
4
5
for(i = 8; i <= 190; i++)
{
	if (GetAsyncKeyState(i) == -32767)
		{//captured key}
}


When does GetAsyncKeyState return -32767 and what does it mean?
GetAsyncKeyState returns a 16-bit signed value. The high bit is set when the current real-time state of the key indicates that it is being held down.

The low bit is set when the key has transitioned from a released to a pressed state (like when the key is first pressed). Though the MSDN documentation indicates this is not reliable.

The value of all other bits should be assumed to be "undefined" and you should discard them. I would not recommend assuming they are 0 because they might not be a in a future version.

That said... you should NOT look for absolute return values. IE: checking for -32767 is wrong. Instead, you should mask out the bit you're interested in:

1
2
3
4
5
6
7
8
if(GetAsyncKeyState(x) & 0x8000)
{
  // high bit is set.  Key is currently held down.
}
if(GetAsyncKeyState(x) & 0x0001)
{
  // low bit is set.  Key just transitioned from released to pressed.
}
Last edited on
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646293%28v=vs.85%29.aspx
If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.

GetAsyncKeyState returns a 16-bit short value. When it has value -32767 the bits are 1000 0000 0000 0001. As you can see both the most significant bit and the least significant bit is set so from the description follows that the key is down and that it has been pressed down since last time you called GetAsyncKeyState.

The page also says you should not rely on the least significant bit because other applications can interfere. For that reason it is better that you simply check the most significant bit (ignoring all other bits) by using the bitwise AND operator & instead of the equal to operator ==, like this:
1
2
3
4
5
for(i = 8; i <= 190; i++)
{
	if (GetAsyncKeyState(i) & 0x8000)
		{//captured key}
}
Both good answers. But why does this work? I mean the -32767 . And it doesnt make copies of the key if i want to store it. But if i use the 0x8000 it gets the keys to fast.
Last edited on
But why does this work? I mean the -32767


-32767 in hex is 0x8001 (as a 16-bit signed integer)

This means both (x & 0x8000) and (x & 0x0001) will be true.

This means:
- The real-time state of the key is being held down (x & 0x8000)
- The key has just transitioned from released to pressed (x & 0x0001)

Again note that it is a bad idea to compare directly with ==.. since some other bits may be set. If for example, they decide to change functionality to make bit 1 return something else regarding the key state... GetAsyncKeyState might return 0x8003. In which case comparing to -32767 will fail, but the &0x8000 and/or &0x0001 checks will still work just fine.

And it doesnt make copies of the key if i want to store it.


I don't understand what you mean by this. GetAsyncKeyState doesn't make copies of anything... it just tells you the state of the key.

But if i use the 0x8000 it gets the keys to fast.


The 0x8000 bit of GetAsyncKeyState gives you the real time state of the key. This means that at the moment you call the function, the bit will be set if the key is currently being held down.... or it will be clear if the key is not being held down.

So if you are spinning in a loop which calls GetAsyncKeyState 1000 times per second for a single key... and the user presses the key for only half a second... this means GetAsyncKeyState will return the high bit set for 500 calls.

If you just want to know whether or not the user just pressed the key for the first time (as opposed to seeing if it's down at this exact moment), you have a few options:

1) Use bit 0 instead of bit 15 (ie: & 0x0001). But again note this can be unreliable as other programs on the machine might interfere with the keystate reported.

2) Keep your own copy of the previous state so that you can see when it transitioned from up to down. Something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// at some larger scope:
bool was_pressed = false;

bool IsKeyPressed()
{
    bool is_pressed = (GetAsyncKeyState(x) & 0x8000) != 0;
    // is_pressed will be true if the key is currently being held down

    if(!was_pressed && is_pressed) // if it wasn't down before, but is down now, they
    {    // just pressed it
        was_pressed = is_pressed;
        return true;
    }

    // otherwise, it either is not held down, or it was already down... so it was not just
    //  pressed
    was_pressed = is_pressed;
    return false;
}


or 3) Don't use GetAsyncKeyState, and instead use some other mechanism for getting the key press. IE: catch and process the WM_KEYDOWN message.
bool is_pressed = (GetAsyncKeyState(x) & 0x8000) != 0;
Excellent.
Topic archived. No new replies allowed.