winapikeykeyboard-input

WM_CHAR doesn't work when IsDialogMessage() is used in the main loop


I inserted IsDialogMessage() in my main loop, in order to the tab key work in the tab control(in my real code) but the WM_CHAR message stopped working. WM_KEYDOWN still is working but I was planning to deal with raw chars in WM_CHAR and key combinations in WM_KEYDOWN hence I'll be handling both for keyboard input. Why did it stop working? what am I missing?

here's full code:

#pragma comment(lib, "user32.lib")

#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#include <windows.h>
#include <assert.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND hMainWindow;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PWSTR lpCmdLine, int nCmdShow) {

    MSG  msg = {0};
    WNDCLASSW wc = {0};
    wc.lpszClassName = L"window1";
    wc.hInstance     = hInstance;
    wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
    wc.lpfnWndProc   = WndProc;
    wc.hCursor       = LoadCursor(0, IDC_ARROW);

  
    if(!RegisterClass(&wc)) {
        assert(!"register window failed!");
    }

    hMainWindow = CreateWindow(wc.lpszClassName, L"dear window",
                  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                  100, 100, 330, 270, 0, 0, hInstance, 0);

    while (GetMessage(&msg, NULL, 0, 0))
    {
 
        if (!IsDialogMessage(hMainWindow, &msg))
        { 
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam) {

    switch(msg) {

        case WM_CREATE:
      
            CreateWindowW(L"Static", L"this is label1", 
                WS_CHILD | WS_VISIBLE | SS_LEFT,
                20, 20, 300, 230, 
                hwnd, (HMENU) 1, NULL, NULL);
            break;

        case WM_DESTROY:

            PostQuitMessage(0);
            break;

        case WM_CHAR:
        {
            static wchar_t buffer[2] = {0};

            buffer[0] = wParam;
            MessageBox(0, buffer, L"you typed", MB_OK);
        }
        break;
    }

    return DefWindowProcW(hwnd, msg, wParam, lParam);
}

Solution

  • The WM_CHAR message is sent to the window that has the current keyboard focus. You are trying to catch WM_CHAR messages in the WndProc of your dialog window, but if your dialog window has any focusable child controls on it then the WndProc of the dialog window will not receive the WM_CHAR messages, they will be sent to the WndProc of the child control that has focus. So, you will have to subclass the child controls to catch the WM_CHAR messages.

    Otherwise, just handle the keyboard messages inside your message loop before passing them to IsDialogMessage()/TranslateMessage().