简体   繁体   English

无法处理 WM_KEYDOWN 消息

[英]Can't handle WM_KEYDOWN message

I'm trying to handle WM_KEYDOWN message using following wndproc and winmain but when I press a key(ie arrow keys which ascii value 24, 25, 26, 27) it doesn't handled.我正在尝试使用以下 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;
}

Why below case doesn't work?为什么下面的情况不起作用? And how can I handle WM_KEYDOWN?我该如何处理 WM_KEYDOWN?

case WM_KEYDOWN:
    PRESSED_KEY = wParam;
    break;

UPDATE更新

When I minimize and maximize window again, WM_KEYDOWN processed but if I click any button, it isn't working.当我再次最小化和最大化 window 时, WM_KEYDOWN已处理,但如果我单击任何按钮,它就不起作用。

According to the WM_KEYDOWN document:根据WM_KEYDOWN文件:

Posted to the window with the keyboard focus when a nonsystem key is pressed.发布到 window 按下非系统键时键盘焦点。 A nonsystem key is a key that is pressed when the ALT key is not pressed.非系统键是在未按下 ALT 键时按下的键。

However, there are other buttons and edit boxes in your window. So when you press other buttons or click on the edit box, the focus will be on that window.which causes the WndProc function to be unable to process the WM_KEYDOWN message.但是你的window里面还有其他的按钮和编辑框,所以当你按下其他按钮或者点击编辑框的时候,焦点会在那个window上,导致WndProc function无法处理WM_KEYDOWN消息。

You can use the SetFocus function to set the keyboard focus window.Then you can get the WM_KEYDOWN message through the main window, and display the value through the Edit control.可以使用SetFocus function设置键盘焦点window。然后可以通过主window获取WM_KEYDOWN消息,通过Edit控件显示数值。

Like the following code:像下面的代码:

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

Of course, if you don't want to focus on a specific window to get keyboard information, I recommend you use the SetWindowsHookEx function to get the global keyboard message, without focusing on a specific window.当然,如果你不想专注于特定的window来获取键盘信息,我建议你使用SetWindowsHookEx function来获取全局键盘信息,而不是专注于特定的window。

Edit:编辑:

If you want to handle all WM_KEYDOWN messages, you can use the SetWindowsHookEx function.如果你想处理所有的WM_KEYDOWN消息,你可以使用SetWindowsHookEx function。

You only need to modify a few parts of your code:您只需要修改代码的几个部分:

1.Add a function to handle the keyboard: 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.Set the hook process to the keyboard in the main function: 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.Finally, don't forget to delete the hook process after the program ends: 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;
        ...
    }
}

In this way, you don't need to process the message of WM_KEYDOWN in WndProc .这样就不需要在WndProc中处理WM_KEYDOWN的消息了。 The message of pressing the key is processed in the KeyboardProc function, and the value of the key is displayed in the Edit control.按键消息在KeyboardProc function中处理,在Edit控件中显示按键的值。

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

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