0

Is there a way of detecting keyboard input within the message loop. Here is something I've tried below:

LRESULT D3DApp::MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch( msg )
    {     
    // WM_DESTROY is sent when the window is being destroyed.
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;

    case WM_KEYDOWN:
        BYTE keyboardState[256];

        if (keyboardState[DIK_W]) {
            OutputDebugStringW(L"W Button Pressed\n");
        }  

        if (keyboardState[DIK_A]) {
            OutputDebugStringW(L"A Button Pressed\n");
        } 

        if (keyboardState[DIK_S]) {
            OutputDebugStringW(L"S Button Pressed\n");
        } 

        if (keyboardState[DIK_D]) {
            OutputDebugStringW(L"D Button Pressed\n");
        }
        return 0;
    }
    return DefWindowProc(hwnd, msg, wParam, lParam);
}

The problem is the it seems to return all of the keyboard states: Output is as follows...

W Button Pressed
A Button Pressed
S Button Pressed
D Button Pressed

How can I implement this so it just detects the key input pressed. I'm new so this might be a stupid implementation :)

1
  • win32com is python-specific, this has nothing to do with Python does it? I will remove tag, if mistake just re-add it. Commented Apr 15, 2014 at 15:49

2 Answers 2

3

You never set the elements when a key is pressed.

You are also using the keyboardState array as a local variable. You must make it global or static, because each time the MsgProc function is called the keyboardState is allocated on the stack, and there is no guarantee of its contents, which may have been modified by previous function calls using the same memory space.

In your code basically each element of keyboardState has 255/256 chance of being non-zero, and you are detecting that instead of real key presses.

If you are not accessing keyboard states from outside, don't bother with the array - just use the wParam argument of the MsgProc function:

 case WM_KEYDOWN:

    if (wParam == DIK_W) {
        OutputDebugStringW(L"W Button Pressed\n");
    }  

    if (wParam == DIK_A) {
        OutputDebugStringW(L"A Button Pressed\n");
    } 

    if (wParam == DIK_S) {
        OutputDebugStringW(L"S Button Pressed\n");
    } 

    if (wParam == DIK_D) {
        OutputDebugStringW(L"D Button Pressed\n");
    }
    return 0;

(Assuming your DIK_ key values are the same as WinAPI's VK_ key codes)

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the detailed reply. I tried what you mentioned however it doesn't seem to step into any of the if statements even when pressing WASD. You mention my DIK values should be the same as WinAPI's VK_codes. What is this? :)
@Ben ah yes I don't know what your DIK values are, but the wParam value uses Microsoft's own set of standard keycodes, with the VK_ prefix. Unfortunately for the QWERTY and numpad keys you need to define them yourself. See msdn.microsoft.com/en-us/library/windows/desktop/… for a list of codes.
3

You are not initializing keyboardState before using it:

case WM_KEYDOWN:
{
    BYTE keyboardState[256];
    ::GetKeyboardState(keyboardState); // <-- ADD THIS!
    ...
    return 0;
}

Alternatively, use Get(Async)KeyState() instead:

case WM_KEYDOWN:
{
    if (GetKeyState('W') & 0x8000) {
        OutputDebugStringW(L"W Button is Down\n");
    }  

    if (GetKeyState('A') & 0x8000) {
        OutputDebugStringW(L"A Button is Down\n");
    } 

    if (GetKeyState('S') & 0x8000) {
        OutputDebugStringW(L"S Button is Down\n");
    } 

    if (GetKeyState('D') & 0x8000) {
        OutputDebugStringW(L"D Button is Down\n");
    }

    return 0;
}

1 Comment

Note that with GetKeyboardState, you should also be testing the specific bit that tells you whether the key is pressed. Most of the other bits are unspecified, and could--in theory--be used for other things in the future. Using GetKeyboardState, GetKeyState, or GetAsynchKeyState (especially the latter) seems weird in response to a WM_KEYDOWN since the WPARAM tells you which key generated this message. I could see using GetKeyState to check if a combining key, like VK_CONTROL, is also pressed. I could see using GetKeyboardState per frame in a game, but it's odd in a WM_KEYDOWN handler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.