为什么PostMessage在全局热键处理程序中调用时无效?

时间:2015-09-07 20:51:45

标签: winapi

我正在编写的GUI应用程序确实将一个keydown事件发送到另一个窗口cmd.exe

PostMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0);

WM_CREATEWM_KEYUP等事件(cmd.exe中出现新行)时,该事件发送得很好。

然后我使用RegisterHotKey设置了一个全局热键。在WM_HOTKEY处理程序中,我成功接收了按键,但PostMessage不再有效。

如何解决这个问题?

完整示例,尽可能缩小:

#include <iostream>
#include <Windows.h>

using namespace std;

const char g_szClassName[] = "myWindowClass";

BOOL CALLBACK enumWindows(HWND hwnd, LPARAM lParam) {
    char winTitle[1024*10];
    GetWindowText(hwnd, winTitle, sizeof(winTitle));
    if (strstr(winTitle, "cmd.exe") != NULL) {
        cout << "Sending a message to window " << hwnd << ": " << winTitle << endl;
        PostMessage(hwnd, WM_KEYDOWN, VK_RETURN, 0);
    }
    return TRUE;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch(msg) {
        case WM_CREATE:
            // register hotkey ctrl+alt+s
            RegisterHotKey(hwnd, 100, MOD_ALT | MOD_CONTROL, 'S');
            break;
        case WM_CLOSE:
            DestroyWindow(hwnd);
            break;
        case WM_DESTROY:
            EnumWindows(enumWindows, 0);
            PostQuitMessage(0);
            break;
        case WM_HOTKEY:
            // hotkey ctrl+alt+s fired
            EnumWindows(enumWindows, 0);
            break;
        case WM_KEYUP:
            EnumWindows(enumWindows, 0);
            break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// just init stuff, do not waste your time
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    RegisterClassEx(&wc);
    hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, "Test", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 240, 120, NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while(GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

Windows 7 64位

1 个答案:

答案 0 :(得分:5)

Raymond Chen已经记录了为什么这不能按照你期望的方式工作(PostMessage IS正常工作,但另一个窗口的响应取决于实际的键盘状态,就像我在评论中推测的那样)。看他的博客文章: