WM_KEYDOWN or GetKeyState(...) for character control

Let say I have a windows game where the user moves a player with WASD... Would I place a switch case in WinProc(...) involving WM_KEYDOWN, or would I check GetKeyState(...) inside the Windows Message loop?

This is the message loop I'll be using
1
2
3
4
5
6
7
8
9
10
11
MSG msg;
while(true)
    while(PeekMessage(&msg, NULL, NULL, NULL, PM_REMOVE)){
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    //If no messages do graphics handling and stuff here
    if(msg.message == WM_QUIT)
        break;
    // KeyCheck Position 1 //
}


This is the Windows Procedure for messages
1
2
3
4
5
6
7
8
9
10
11
12
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    //Look for message to do with game or window
    switch(message){
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
        break;
    }
    //KeyCheck Position 2
    //Send any unresolved message back to windows, we dont care about them :)
    return DefWindowProc(hWnd, message, wParam, lParam);
}


My instincts tell me to leave the procedure for more important stuff (not quite sure what yet) and to use GetKeyState(...) in "KeyCheck Position 1".
But not only that, I'm not sure whether the WM_KEYDOWN message repeats while the key is down... MSDN says there's an autorepeat feature but I'm not sure whether this is similar to how typing works where it pauses for a while before sending a spam of more messages, or whether it'll completly spam the message queue and not let any other message in for a while.
Bump... Could do with an answer, personally I don't think this is a very trivial question for anyone who considers themselves at least intermediate with windows.
I'd go with your instinct and use GetKeyState(). It seems more precise in your case.
In fact, for a game I'd use DirectX (DirectInput that is).
It's pretty useful if the user/player presses a lot of keys at the same time and you want to keep track of all of these including control keys (Ctrl, Alt, Shift) function keys and the cursor/navigation keys.


If you use this inside of your Callback loop then the function will only be called whenever a message is sent to the window, that means that GetKeyState will not be called until the key is held down for a time that exceeds the repeat delay set on the system (this setting is in the Control Panel in case you're curious) or another new action is taken such as moving the window or the mouse or pressing another key or a hundred other things.
I used to be doing things like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

bool Keys[0x100] = {0};

LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    //Look for message to do with game or window
    switch(message){
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
        break;
    case WM_KEYDOWN:
        Keys[ wParam&0xFF ] = 1;
        break;
    case WM_KEYUP:
        Keys[ wParam&0xFF ] = 0;
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}


Just with a different, safer pattern that involved using classes to keep track of variables, but that was the point.

After this, you can check Keys[ 'W' ] to check if the W key is pressed.
Remember to use UPPERCASE letters.
You can also check Keys[ VK_SPACE ] or similars, you should be able to understand what has been done there.
Last edited on
Well as I said I was thinking of either one of two ideas...

Currently I have this
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//inside WinMain(){
//At end
    MSG msg;
    while(true){
        while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE){
            TranslateMessage(&msg);
            DispatchMessage(&msg);
         }
        if(msg == WM_QUIT)
            break;
        //Do graphics rendering and stuff here
    }
}


LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){
    switch(message){
    //create/destroy and other cases
    case WM_KEYDOWN:
        Game.KeyPress(wParam, lParam); //Function in GAME class Game, to determine if key will do anything
        break;
    }
}


I wanted to keep the WinProc nice and tidy so I call a separate function for determining which key is pressed and whether to do anything with it... Would this be sufficient or would there be a pause for when the KEY_DOWN is sent because of the auto-repeat 1st delay?

If that doesn't work, my second choice would be to call a function which checks all keys of any value in the current game state to see if the key state is down.
In the bit which says Do graphics rendering and stuff here I would add a call to something like Game.CheckKeys();, inside which will be a load of GetKeyState(...); calls.

Which would be the most advised? Or perhaps another method with example?
I guess using GetKeyState, if you have already a Message Loop, is useless.
You better keep track of pressed keys by yourself like I posted above.
This way you won't need a possibly long call to GetKeyState.
Again, the way I posted my snippet above, you can check all the pressed Keys by doing a simple:
bool MovingForward = Keys['W']; which is kinda simple.

EDIT: Just another time you've mistaken msg.message writing msg :'D
Last edited on
Yes that is yet another time I have mistaken msg for msg.message... And I suppose it's not a bad method that...
Well thanks alot to everyone the tried to help, and thanks @EssGeEich for the method suggestion and example.
Topic archived. No new replies allowed.