Win32 Input and GetAsyncKeyState

Started by
15 comments, last by Rodaxoleaux 12 years, 6 months ago
Windows input has thwarted all my attempts to attempt to even semi-understand it. I've read through the information about the different bits and how the least sign. bit of GetAsyncKeyState only works sometimes (which I suppose shouldn't be used at all since it is not reliable). If I use the function at all, it will work once, for one key, and then all input to that window doesn't register at all. I know I'm doing something wrong programmatically but I can't figure out what.
if (GetAsyncKeyState(VK_F10) >> 8 < 0 || GetAsyncKeyState(VK_F10) >> 1 < 0 || GetAsyncKeyState(VK_F10) < 0)
{
TerminalOn = !TerminalOn;
if (GetFocus() != hwnd)
SetFocus(hwnd);
ToSetWindow = true;
}


I've changed this actually a bunch of times only to produce the same result. Any ideas/advice? (and if that advice is "don't use GetAsyncKeyState()", i'd thank you, but I do need a form of keyboard input that does not rely on focus or the window being shown (as it is hidden when not active))
Advertisement
Why do you call the function three times? This changes the behavior of the function, esp. with regards to the least-significant bit, which is well documented. It's also well documented that you basically shouldn't ever test the LSB because it's not reliable.

Also, why are you checking if it's < 0 after shifting bits? What is that supposed to accomplish?

It seems to me like you're just randomly putting things in in hopes that it will work, without actually understanding the function. What happens if you use the canonical example of the function that can be found all over Google as the "correct" usage?

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Ehm, whatever you are trying and just putting in there is not logical at all, like ApochPiQ said. If you are creating your own window with a callback try to implement some kind of listener which gets information when a WM_KEY or WM_MOUSE is received. Wrap it up in a class which you can use in any other location to get information on a key.

My general input manager goes like this:

switch(uMsg){
case WM_KEYDOWN:
case WM_KEYUP:
{
if( uMsg == WM_KEYUP ) {
SomeListener::SetThisToReleased( wParam );
}else{
SomeListener::SetThisToPressed( wParam );
}
break;
}

case WM_MOUSEMOVE:
{
SomeListener::SetNewMousePosition( wParam, lParam );
break;
}
case WM_LBUTTONUP:
{
SomeListener::SetMousePressed( wParam );
break;
}
case WM_LBUTTONDOWN:
{
SomeListener::SetMouseRelease( wParam );
break;
}
}




Try to split everything up so you can easily manage it when something is wrong. This way of setting up a static listener makes you able to use it throughout the entire project, use key and/or mouse input anywhere you like.
If I've helped you in any way please push the reputation button, thanks!

Abstraction is my choice of words.
Portfolio: http://www.0x3a.com/
Blog: http://blog.0x3a.com/
I was basically adding random ways once I figured out that the "way that's posted all over Google" doesn't produce the result I want (in other words, the same as what is happening now). I already said the part about the lsb but I thought it was worth a try to try it (and produced the same result), I tried using the WM_KEYDOWN/UP messages but they didn't work after ShowWindow(hwnd,NULL) hiding the window, so I scratched that.

EDIT:: In fact, the normal GetAsyncKeyState() works perfectly as long as there is focus on the window. I'm confused. Isn't it supposed to work regardless?
Not necessarily. The reason it exists is, as hinted at by the documentation, largely for backwards compatibility. It isn't really a great way to grab key state, regardless of whether or not your process has input focus.

If you need to monitor input across all processes on the current desktop, try hooks.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Indeed. I just read this
Window Visibility
A window can be either visible or hidden. The system displays a visible window on the screen. It hides a hidden window by not drawing it. If a window is visible, the user can supply input to the window and view the window's output. If a window is hidden, it is effectively disabled. A hidden window can process messages from the system or from other windows, but it cannot process input from the user or display output


from the Microsoft website. I will look up more information on hooks. Thanks.



Windows input has thwarted all my attempts to attempt to even semi-understand it. I've read through the information about the different bits and how the least sign. bit of GetAsyncKeyState only works sometimes (which I suppose shouldn't be used at all since it is not reliable). If I use the function at all, it will work once, for one key, and then all input to that window doesn't register at all. I know I'm doing something wrong programmatically but I can't figure out what.
if (GetAsyncKeyState(VK_F10) >> 8 < 0 || GetAsyncKeyState(VK_F10) >> 1 < 0 || GetAsyncKeyState(VK_F10) < 0)
{
TerminalOn = !TerminalOn;
if (GetFocus() != hwnd)
SetFocus(hwnd);
ToSetWindow = true;
}


I've changed this actually a bunch of times only to produce the same result. Any ideas/advice? (and if that advice is "don't use GetAsyncKeyState()", i'd thank you, but I do need a form of keyboard input that does not rely on focus or the window being shown (as it is hidden when not active))


Also bear in mind that bitwise operators have low precedence; I cannot remember exactly, but I'm pretty sure that evaluates to:

if (GetAsyncKeyState(VK_F10) >> (8 < 0) || GetAsyncKeyState(VK_F10) >> (1 < 0) || GetAsyncKeyState(VK_F10) < 0){ ... }

Every so often, I forget, and run into a problem where a conditional evaluates differently if I don't put extra parentheses before doing a comparison.
You might also find RegisterHotkey useful, depending on what you're trying to do.
You could just use these defines:

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

You could just use these defines:

#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)



The problem the OP has is related to capturing key state when the program window does not have input focus. Your macros will not help with this, unfortunately.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

This topic is closed to new replies.

Advertisement