在 WM_KEYDOW 消息中捕获 VK_UP 无效

catching VK_UP in WM_KEYDOW message not working

window 过程中的这段代码不起作用:

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

            default: 
                break;
        }

我按向上箭头键,但未调用 MessageBox。我错过了什么?

完整代码:

#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;
}

您的消息泵格式不正确。您正在为无模式对话框(通过 CreateDialog 创建的 window)做一些事情,但是您的应用程序中没有这样的 window 类型。因此,您的一些消息被 IsDialogMessage 函数吞没了。

所以不是这个:

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

这个:

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

当我将您的代码更改为该代码时,会出现消息框。