4

How do I handle key presses and key up events in the windows message loop? I need to be able to call two functions OnKeyUp(char c); and OnKeyDown(char c);.

Current literature I've found from googling has lead me to confusion over WM_CHAR or WM_KEYUP and WM_KEYDOWN, and is normally targeted at PDA or Managed code, whereas I'm using C++.

2 Answers 2

11

A typical C++ message loop looks like this

MSG msg;
while (GetMessage(&msg, null, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

The function of TranslateMessage is to generate WM_CHAR messages from WM_KEYDOWN messages, so if you want to see WM_CHAR messages you need to be sure to pass WM_KEYDOWN messages to it. If you don't care about WM_CHAR messages, you can skip that, and do something like this.

extern void OnKeyDown(WPARAM key);
extern void OnKeyUp(WPARAM key);

MSG msg;
while (GetMessage(&msg, null, 0, 0))
{
    if (msg.message == WM_KEYDOWN)
       OnKeyDown (msg.wParam);
    else if (msg.message == WM_KEYUP)
       OnKeyUp(msg.wParam);
    else
    {
       TranslateMessage(&msg);
       DispatchMessage(&msg);
    }
}

Notice that OnKeyDown and OnKeyUp messages are defined as taking a WPARAM rather than a char. That's because the values for WM_KEYDOWN and WM_KEYUP aren't limited to values that fit in a char. See WM_KEYDOWN

More:
Using Messages and Message Queues
https://learn.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues

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

1 Comment

The problem here is that although I would now have code that runs key up and key down, I also have code that is not portable. I would need a way of converting WPARAM into something more portable, instead of taking all my crossplatform code and making it windows only so that I can test for virtual key values, hence 'char' being used. I also don't want to spend a day writtng code for every character to convert
7

Use char c = MapVirtualKey(param,MAPVK_VK_TO_CHAR); to convert virtual key codes to char, and process WM_KEYUP and WM_KEYDOWN and their wParams.

if (PeekMessage (&mssg, hwnd, 0, 0, PM_REMOVE))
{
    switch (mssg.message)
    {
        case WM_QUIT:
            PostQuitMessage (0);
            notdone = false;
            quit = true;
            break;

        case WM_KEYDOWN:
            WPARAM param = mssg.wParam;
            char c = MapVirtualKey (param, MAPVK_VK_TO_CHAR);
            this->p->Input ()->Keyboard ()->Listeners ()->OnKeyDown (c);
            break;

        case WM_KEYUP:
            WPARAM param = mssg.wParam;
            char c = MapVirtualKey (param, MAPVK_VK_TO_CHAR);
            this->p->Input ()->Keyboard ()->Listeners ()->OnKeyUp (c);
            break;
    }
    // dispatch the message
    TranslateMessage (&mssg);
    DispatchMessage (&mssg);
}

Comments

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.