繁体   English   中英

无法处理 WM_KEYDOWN 消息

[英]Can't handle WM_KEYDOWN message

我正在尝试使用以下 wndproc 和 winmain 处理 WM_KEYDOWN 消息,但是当我按下一个键(即 ascii 值为 24、25、26、27 的箭头键)时,它没有被处理。

WndProc

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){
    /*TO CHECK uMsg message*/
    char buff[256];
    _itoa_s(uMsg, buff, 10);
    SetWindowText(hEdit, buff);
    /**********************/
    switch (uMsg)
        case WM_CREATE:
            hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, "Edit", "", WS_CHILD | WS_VISIBLE |ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | WS_VSCROLL, 735, 5, 150, 100, hWnd, NULL, hInst, NULL);
            HButton1 = CreateWindowEx(NULL, "BUTTON", "START", WS_CHILD | WS_VISIBLE | SS_CENTER, 2, 2, 80, 20, hWnd, (HMENU)IDC_BUTTON1, hInst, NULL);
            HButton2 = CreateWindowEx(NULL, "BUTTON", "B", WS_CHILD | WS_VISIBLE | SS_CENTER, 82, 2, 80, 20, hWnd, (HMENU)IDC_BUTTON2, hInst, NULL);
            HButton3 = CreateWindowEx(NULL, "BUTTON", "STOP", WS_CHILD | WS_VISIBLE | SS_CENTER, 162, 2, 80, 20, hWnd, (HMENU)IDC_BUTTON3, hInst, NULL);
            Hmainbmp = CreateWindowEx(NULL, "STATIC", "", WS_CHILD | WS_VISIBLE | SS_BITMAP | WS_THICKFRAME, 1, 23, 600, 500, hWnd, NULL, hInst, NULL);
            break;
        case WM_KEYDOWN:
            PRESSED_KEY = wParam;
            break;
        case WM_COMMAND:
                    break;
            case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            return(DefWindowProc(hWnd, uMsg, wParam, lParam));
    return(0L);
}

WinMain

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow){
    MSG      msg;
    WNDCLASSEX wc;
    HMENU MainMenu, FileMenu;
    MainMenu = CreateMenu();
    FileMenu = CreatePopupMenu();
    AppendMenu(FileMenu, MF_STRING, IDC_OPEN, "Open");
    AppendMenu(MainMenu, MF_POPUP, (UINT_PTR)FileMenu, "FILE");

    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW);
    wc.lpszMenuName = lpszAppName;
    wc.lpszClassName = lpszAppName;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.hIconSm = (HICON)LoadImage(hInstance, lpszAppName, IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR);

    if (!RegisterClassEx(&wc)) return(FALSE);

    hInst = hInstance;
    hWnd = CreateWindowEx(0, lpszAppName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 900, 600, NULL, MainMenu, hInstance, NULL);


    if (!hWnd) return(FALSE);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    return (int)msg.wParam;
}

为什么下面的情况不起作用? 我该如何处理 WM_KEYDOWN?

case WM_KEYDOWN:
    PRESSED_KEY = wParam;
    break;

更新

当我再次最小化和最大化 window 时, WM_KEYDOWN已处理,但如果我单击任何按钮,它就不起作用。

根据WM_KEYDOWN文件:

发布到 window 按下非系统键时键盘焦点。 非系统键是在未按下 ALT 键时按下的键。

但是你的window里面还有其他的按钮和编辑框,所以当你按下其他按钮或者点击编辑框的时候,焦点会在那个window上,导致WndProc function无法处理WM_KEYDOWN消息。

可以使用SetFocus function设置键盘焦点window。然后可以通过主window获取WM_KEYDOWN消息,通过Edit控件显示数值。

像下面的代码:

case WM_KEYDOWN:
    PRESSED_KEY = wParam;
    _itoa_s(wParam, buff, 10);
    SetWindowTextA(hEdit, buff);
    break;

当然,如果你不想专注于特定的window来获取键盘信息,我建议你使用SetWindowsHookEx function来获取全局键盘信息,而不是专注于特定的window。

编辑:

如果你想处理所有的WM_KEYDOWN消息,你可以使用SetWindowsHookEx function。

您只需要修改代码的几个部分:

1.添加一个function来处理键盘:

LRESULT __stdcall KeyboardProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    char buff[256] = "";
    PKBDLLHOOKSTRUCT key = (PKBDLLHOOKSTRUCT)lParam;
    //a key was pressed
    if (wParam == WM_KEYDOWN && nCode == HC_ACTION)
    {
        _itoa_s(key->vkCode, buff, 10);
        SetWindowTextA(hEdit, buff);
    }
    return CallNextHookEx(NULL, nCode, wParam, lParam);
}

2.在main function中设置对键盘的hook进程:

HHOOK _k_hook;
int WINAPI WinMain(_In_  HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_  LPSTR szCmdLine, _In_  int nCmdShow)
{
    MSG      msg;
    WNDCLASSEX wc;
    HMENU MainMenu, FileMenu;
    _k_hook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardProc, NULL, 0);
    ...
}

3.最后,程序结束后别忘了删除hook进程:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    HWND HButton1, HButton2, HButton3, Hmainbmp;
    switch (uMsg)
    {
        ...
    case WM_DESTROY:
        if (_k_hook)
            UnhookWindowsHookEx(_k_hook);
        PostQuitMessage(0);
        break;
        ...
    }
}

这样就不需要在WndProc中处理WM_KEYDOWN的消息了。 按键消息在KeyboardProc function中处理,在Edit控件中显示按键的值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM