Mikko-Pentti Einari Eronen Mikko-Pentti Einari Eronen - 2 months ago 28
C++ Question

Win32 WM_KEYDOWN and WM_KEYUP and statuses getting "stuck"

Below is a code I use to capture what ever the key is being pressed or not and I update the statuses of the keys according to their states.
I keep the statues in my simple array of values 0,1,2,3.
formatted as: keyboardmap[256] = {0};

Problem is, what ever I try to do, keys keep getting stuck at some point. They never get reset back to zero as if the WM_KEYUP would not fire up properly.

while (true)
{

if ( PeekMessage(&msg, 0, 0, 0, PM_REMOVE) )
{
TranslateMessage(&msg);
DispatchMessage(&msg);

if (msg.message == WM_QUIT)
{
break;
}

// Check for keystates and update them.
if (msg.message == WM_KEYDOWN)
{
// Fetch the key state.
unsigned int keycode = msg.wParam;
unsigned int cstate = engine.GetKeyState(msg.wParam);

if (engine.GetKeyState(keycode) == 0)
{
engine.SetKeyState(keycode, 1); // Just started pressing.
}
else
{
engine.SetKeyState(keycode, 2); // Actively pressed down.
}
}
else if (msg.message == WM_KEYUP)
{
// Fetch the key state.
unsigned int keycode = msg.wParam;
unsigned int cstate = engine.GetKeyState(msg.wParam);

if ( engine.GetKeyState(keycode) == 2)
{
engine.SetKeyState(keycode, 3);
}
else
{
engine.SetKeyState(keycode, 0);
}
}
}
}

Answer

That's not how the message loop is supposed to be. Use the following example for a game engine where you need to constantly update the game/screen:

WNDCLASSEX wc = { sizeof(WNDCLASSEX) };
wc.lpfnWndProc = WndProc;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = L"WindowClass";
RegisterClassEx(&wc);

CreateWindow(...);

MSG msg = { 0 };
while (msg.message != WM_QUIT)
{
    if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    else
    {
        engine.update();
    }
}

Window's messages should be handled in separate window procedure:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
    case WM_KEYDOWN:
        break;

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProc(hWnd, msg, wParam, lParam);
}