Search code examples
winapikeydownarrow-keys

catching VK_UP in WM_KEYDOW message not working


this piece of code in the window procedure isn't working:

    case WM_KEYDOWN:
        switch(wParam)
        {
             case VK_UP:
                MessageBox(NULL, L"key up", L"", MB_OK);
             break;

            default: 
                break;
        }

I press the arrow up key but the MessageBox isn't being called. What am I missing?

full code:

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

#define WIN32_LEAN_AND_MEAN
#define UNICODE
#define _UNICODE

#ifdef UNICODE
#define STRSPLIT wcsrchr
#else
#define STRSPLIT strrchr
#endif

#define __FILENAME__ (STRSPLIT(TEXT(__FILE__), '/') ? STRSPLIT(TEXT(__FILE__), '/') + 1 : TEXT(__FILE__))
#define NAMEOF(s) TEXT(#s)
#define COUNTOF(a) (sizeof(a)/sizeof(a[0]))

#include <windows.h>
#include <strsafe.h>
#include <CommCtrl.h>

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void setUpScrollBar(HWND hwnd);
void ErrorExit(LPWSTR lpszFunction, int line, LPWSTR filename);
DWORD ShowLastError(LPWSTR lpszFunction, int line, LPWSTR filename);
void InsertTabItem(HWND tabHwnd, UINT id, LPWSTR text);
void CreateTab(HWND hwnd);

HWND hTab;

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

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

  
    RegisterClassW(&wc);
    HWND hWnd =
    CreateWindowW(wc.lpszClassName, L"foo",
                  WS_OVERLAPPEDWINDOW | WS_VISIBLE,
                  100, 100, 330, 180, 0, 0, hInstance, 0);

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

    return (int) msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, 
    WPARAM wParam, LPARAM lParam)
{
    static int g_scrollY;

    switch(msg)
    {
        case WM_CREATE:
            CreateWindowW(L"Static", L"This is label 1...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 10, 130, 25, hwnd, (HMENU) 18, NULL, NULL);
            CreateWindowW(L"Static", L"This is label 2...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 40, 130, 25, hwnd, (HMENU) 19, NULL, NULL);
            CreateWindowW(L"Static", L"This is label 3...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 70, 130, 25, hwnd, (HMENU) 19, NULL, NULL);
            CreateWindowW(L"Static", L"This is label 4...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 100, 130, 25, hwnd, (HMENU) 19, NULL, NULL);
            CreateWindowW(L"Static", L"This is label 5...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 130, 130, 25, hwnd, (HMENU) 19, NULL, NULL);
            CreateWindowW(L"Static", L"This is label 6...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 160, 130, 25, hwnd, (HMENU) 19, NULL, NULL);
            CreateWindowW(L"Static", L"This is label 7...",
                WS_VISIBLE | WS_CHILD | WS_TABSTOP | WS_BORDER,
                50, 190, 130, 25, hwnd, (HMENU) 19, NULL, NULL);

            setUpScrollBar(hwnd);
            break;

          case WM_VSCROLL:
            int action = LOWORD(wParam);
            //HWND hScroll = (HWND)lParam;
            int pos = -1;
            if (action == SB_THUMBPOSITION || action == SB_THUMBTRACK) {
                pos = HIWORD(wParam);
            } else if (action == SB_LINEDOWN) {
                pos = g_scrollY + 30;
            } else if (action == SB_LINEUP) {
                pos = g_scrollY - 30;
            } 
            if (pos == -1)
                break;
            
            SCROLLINFO si = { 0 };
            si.cbSize = sizeof(SCROLLINFO);
            si.fMask = SIF_POS;
            si.nPos = pos;
            si.nTrackPos = 0;
            SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
            GetScrollInfo(hwnd, SB_VERT, &si);
            pos = si.nPos;
            POINT pt;
            pt.x = 0;
            pt.y = pos - g_scrollY;
            HDC hdc = GetDC(hwnd);
            LPtoDP(hdc, &pt, 1);
            ReleaseDC(hwnd, hdc);
            ScrollWindow(hwnd, 0, -pt.y, NULL, NULL);
            g_scrollY = pos;
            return 0;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        
        case WM_KEYDOWN:
            switch(wParam)
            {
                 case VK_UP:
                    MessageBox(NULL, L"key up", L"", MB_OK);
                 break;

                default: 
                    break;
            }
        break;
    }

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

void setUpScrollBar(HWND hwnd)
{
    RECT rc = { 0 };
    GetClientRect(hwnd, &rc);
    SCROLLINFO si = { 0 };
    si.cbSize = sizeof(SCROLLINFO);
    si.fMask = SIF_ALL;
    
    si.nMin = 0;
    si.nMax = 220;
    si.nPage = (rc.bottom - rc.top);
    si.nPos = 0;
    si.nTrackPos = 0;

    SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}

void ErrorExit(LPWSTR lpszFunction, int line, LPWSTR filename)
{
    DWORD dw = ShowLastError(lpszFunction, line, filename);
    ExitProcess(dw);
}

DWORD ShowLastError(LPWSTR lpszFunction, int line, LPWSTR filename)
{
    #define MAX_DIGITS 16

    DWORD dw = GetLastError();
    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER |
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0,
        NULL
    );

    lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT, 
            (lstrlen((LPCTSTR)lpMsgBuf) +
            lstrlen((LPCTSTR)lpszFunction) + 40 +
            (line > 0 ? MAX_DIGITS : 0) +
            (filename != NULL ? lstrlen(filename) : 0)) *
            sizeof(TCHAR)
    );
    StringCchPrintf((LPTSTR)lpDisplayBuf,
                    LocalSize(lpDisplayBuf) / sizeof(TCHAR),
                    TEXT("%s failed with %d: %s"),
                    lpszFunction, dw, lpMsgBuf
    );
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    return dw;
}

Solution

  • Your message pump is not correctly formed. You're doing something for modeless dialogs (a window created via CreateDialog), but you have no such window type in your app. Hence, some of your messages are getting swallowed by the IsDialogMessage function.

    So instead of this:

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

    This:

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

    When I changed your code to that, the message box would appear.