【问题标题】:Why PostMessage has no effect when called from within a global hotkey handler?为什么从全局热键处理程序中调用 PostMessage 无效?
【发布时间】:2015-09-08 05:00:07
【问题描述】:

我正在编写的一个 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 位

【问题讨论】:

  • 也许WM_KEYDOWN 处理程序会检查其他键的状态,这些键在热键触发的瞬间被按下?
  • 伪造输入并且做错了,好吧,错了。使用官方自动化界面,您可能会获得更好的成功:UI Automation

标签: winapi


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 2012-10-04
    • 1970-01-01
    • 2016-07-12
    • 2013-06-12
    • 2010-09-10
    • 2010-09-23
    • 1970-01-01
    • 2023-03-31
    • 2018-06-02
    相关资源
    最近更新 更多