-1

I'm trying to handle key up and key down messages for arrow keys and A, W, S, D characters.

I can handle arrow keys' up and down behavior using WM_KEYUPand WM_KEYDOWN.

But when I try to handle above characters' up and down behavior, it doesn't work properly.

I tried WM_KEYUPand WM_KEYDOWN to handle chracters. But after I changed them to WM_CHAR and WM_DEADCHAR. But it still doesn't work.

For characters I can handle first few key down and up messages, then program doesn't handle these. But for arrow keys, program works properly.

I'm new in this, didn't found how to handle character's up and down behaviors.

Below is the last code (Just WndProc function)I tried.

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    switch (uMsg)
    {
    case WM_CREATE:
        Hmainbmp = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE | SS_BITMAP | WS_THICKFRAME, 1, 23, WINDOW_WIDTH, WINDOW_HEIGHT, hWnd, nullptr, hInst, nullptr);
        start_game();
        break;

    case WM_CHAR:
        PRESSED_KEY = (int)wParam;
        if (PRESSED_KEY == 'A' or PRESSED_KEY == 'a') { players[1]->moves.left = true; }
        else if (PRESSED_KEY == 'D' or PRESSED_KEY == 'd') { players[1]->moves.right = true; }
        else if (PRESSED_KEY == 'W' or PRESSED_KEY == 'w') { players[1]->moves.up = true; }
        else if (PRESSED_KEY == 'S' or PRESSED_KEY == 's') { players[1]->moves.down = true; }
        break;

    case WM_DEADCHAR:
        PRESSED_KEY = (int)wParam;
        if (PRESSED_KEY == 'A' or PRESSED_KEY == 'a') { players[1]->moves.left = false; }
        else if (PRESSED_KEY == 'D' or PRESSED_KEY == 'd') { players[1]->moves.right = false; }
        else if (PRESSED_KEY == 'W' or PRESSED_KEY == 'w') { players[1]->moves.up = false; }
        else if (PRESSED_KEY == 'S' or PRESSED_KEY == 's') { players[1]->moves.down = false; }
        break;

    case WM_KEYDOWN:
        PRESSED_KEY = (int)wParam;
        if      (PRESSED_KEY == VK_LEFT)    { players[0]->moves.left    = true; }
        else if (PRESSED_KEY == VK_RIGHT)   { players[0]->moves.right   = true; }
        else if (PRESSED_KEY == VK_UP)      { players[0]->moves.up      = true; }
        else if (PRESSED_KEY == VK_DOWN)    { players[0]->moves.down    = true; }
        break;
    case WM_KEYUP:
        RELEASED_KEY = (int)wParam;
        if      (RELEASED_KEY == VK_LEFT)   { players[0]->moves.left    = false; }
        else if (RELEASED_KEY == VK_RIGHT)  { players[0]->moves.right   = false; }
        else if (RELEASED_KEY == VK_UP)     { players[0]->moves.up      = false; }
        else if (RELEASED_KEY == VK_DOWN)   { players[0]->moves.down    = false; }
        break;
    
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return(DefWindowProc(hWnd, uMsg, wParam, lParam));
    }

    return(0L);
}

start_game() is my main function, I'm using key's up and down messages in that function.

My question is, how can I handle key down and key up behaviors of characters such as A, D?


After I press to A or W program can't handle key up behavior of these characters and any other character's key down behavior like S and D. But at the same time program can handle arrow keys' up and down behavior.


FULL CODE (Vs2019)

  • 2
    is there another window on the window, like an edit box or button that may have stolen the focus? – Andy Feb 09 '21 at 02:30
  • 1
    @Andy No, there is just one window on the window. Let me specifiy this code can handle arrow keys up and down behaviors properly but can't handle characters properly. –  Feb 09 '21 at 02:35
  • 2
    I'm running something locally here, basically using your code, and have no issues. I do see part of your code using `players[1]` and the other part using `players[0]` Is that intentional? – Andy Feb 09 '21 at 02:36
  • 2
    Instead of repeating a vague "doesn't work", could you describe the behavior you expect and the actual behavior? – JaMiT Feb 09 '21 at 02:36
  • 3
    @lapestand Not sure what you expect [`WM_DEADCHAR`](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-deadchar) to be doing there, but it's certainly not related to `WM_KEYUP` the same way `WM_CHAR` is to `WM_KEYDOWN`. – dxiv Feb 09 '21 at 02:43
  • 1
    @Andy I share all code as a github link. Yes they are in the code. –  Feb 09 '21 at 02:44
  • 1
    @dxiv I want to handle key down and key up behaviors of characters. I can handle this behaviors for arrow keys properly but can't handle for characters. I don't know what is the true way to handle these behaviors. –  Feb 09 '21 at 02:46
  • 2
    @lapestand You have `WM_KEYDOWN/UP` to handle keys pressed and released, and you have `WM_CHAR` to handle translated characters. But there is no notion (or message) of "char up". Add some `printf` or other logging to your `WndProc` to get a better picture of what's going on. – dxiv Feb 09 '21 at 02:53

1 Answers1

0

According to WM_DEADCHAR:

WM_DEADCHAR specifies a character code generated by a dead key. A dead key is a key that generates a character, such as the umlaut (double-dot), that is combined with another character to form a composite character.

So the WM_DEADCHAR message is not what you think corresponds to the WM_CHAR message.

You can also use WM_KEYDOWN/WM_KEYUP messages to handle character keys:

case WM_KEYDOWN:
    PRESSED_KEY = (int)wParam;
    if      (PRESSED_KEY == VK_LEFT)    { players[0]->moves.left    = true; }
    else if (PRESSED_KEY == VK_RIGHT)   { players[0]->moves.right   = true; }
    else if (PRESSED_KEY == VK_UP)      { players[0]->moves.up      = true; }
    else if (PRESSED_KEY == VK_DOWN)    { players[0]->moves.down    = true; }
    if (PRESSED_KEY == 'A' or PRESSED_KEY == 'a') { players[1]->moves.left = true; }
    else if (PRESSED_KEY == 'D' or PRESSED_KEY == 'd') { players[1]->moves.right = true; }
    else if (PRESSED_KEY == 'W' or PRESSED_KEY == 'w') { players[1]->moves.up = true; }
    else if (PRESSED_KEY == 'S' or PRESSED_KEY == 's') { players[1]->moves.down = true; }
    break;
case WM_KEYUP:
    RELEASED_KEY = (int)wParam;
    if      (RELEASED_KEY == VK_LEFT)   { players[0]->moves.left    = false; }
    else if (RELEASED_KEY == VK_RIGHT)  { players[0]->moves.right   = false; }
    else if (RELEASED_KEY == VK_UP)     { players[0]->moves.up      = false; }
    else if (RELEASED_KEY == VK_DOWN)   { players[0]->moves.down    = false; }
    if (RELEASED_KEY == 'A' or RELEASED_KEY == 'a') { players[1]->moves.left = false; }
    else if (RELEASED_KEY == 'D' or RELEASED_KEY == 'd') { players[1]->moves.right = false; }
    else if (RELEASED_KEY == 'W' or RELEASED_KEY == 'w') { players[1]->moves.up = false; }
    else if (RELEASED_KEY == 'S' or RELEASED_KEY == 's') { players[1]->moves.down = false; }
    break;
Zeus
  • 3,703
  • 3
  • 7
  • 20
  • When try this code, sometimes directions(player.move in the code) stucks even I release the character. Therefore I have to press & release again to save it. –  Feb 09 '21 at 03:18
  • @lapestand There was an error in the code just now. I used `PRESSED_KEY` when releasing. I have modified the code and you can refer to it. – Zeus Feb 09 '21 at 03:26
  • 2
    A `switch` would make more sense than a bunch of `if`s. But more importantly, note that `WM_KEY(DOWN|UP)` deal with [*virtual key codes*](https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes) only. The virtual key codes for letters A..Z are in the range `0x41..0x5A`, which is the same numeric values as their CAPITAL letters in ASCII, so the key codes in those messages will NEVER be `'a'/'d'/'w'/'s'`, only `A'/'D'/'W'/'S'`. `WM_CHAR`, on the other hand, deals in *textual characters*, and so it will see lowercase letters, if that is what the user actually typed. – Remy Lebeau Feb 09 '21 at 03:33