使用 PostMessage 在失焦的应用程序窗口中模拟/合成简单的按键操作

问题描述 投票:0回答:1

尝试编写一个简单的演示程序,其中控制台的键盘输入被转换为属于其他应用程序进程的目标窗口上的按键。因此,如果我在控制台中键入键盘上的字符“w”,它会转换为发送到目标线程的消息队列的适当消息,该线程使应用程序相信在其窗口处于焦点时按下了“w”键。

这是我试过的:

int main()
{
    println("Enter W, A, S, D or SPACE:");
    while (true)
    {
        int posted_key = NULL;
        int key_char = _getch();
        
        if (key_char==27) break;

        switch(key_char)
        {
            case 119: posted_key = 0x57; break;
            case 97: posted_key = 0x41; break;
            case 115: posted_key = 0x53; break;
            case 100: posted_key = 0x44; break;
            case 32: posted_key = VK_SPACE; break;
        }

        if (posted_key == NULL) continue; // Key isn't W, A, S, D or SPACE

        if (!PostMessage(hndl, WM_KEYDOWN, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) print("Error while posting WM_KEYDOWN"); break;
        if (!PostMessage(hndl, WM_CHAR, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) print("Error while posting WM_CHAR"); break;
        Sleep(100);
        if (!PostMessage(hndl, WM_KEYUP, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) print("Error while posting WM_KEYUP"); break;
    }

    return 0;
}

但是,只有

WM_KEYDOWN
WM_CHAR
消息(每个 1 个)最终实际发布到队列中,而 not
WM_KEYUP
消息,导致应用程序的行为就像无限期地按下键一样。通过在各种应用程序上使用 Spy++,似乎快速按键通常在 3 秒内出现:
WM_KEYDOWN
WM_CHAR
,然后是几分之一秒后的
WM_KEYUP
。所以这就是我试图在我的代码中模拟的,但它显然不起作用。

更重要的是,当我按 W、A、S、D 或 SPACE 时,我的程序立即退出并返回代码 0,并且我的错误消息没有打印出来。因此,要么我的程序崩溃了,要么我对

PostMessage
的调用之一返回了非零值。后者可能不太可能,因为我的错误消息没有打印出来。

我做错了什么?我不能使用

SendInput
SendKeys
来做我想做的事情,因为即使应用程序窗口没有聚焦,我也需要它来工作。

--编辑--

我在原来的

if
条件中格式错误。

int main()
{
    println("Enter W, A, S, D or SPACE:");
    while (true)
    {
        int posted_key = NULL;
        int key_char = _getch();

        if (key_char==27) break;

        switch(key_char)
        {
            case 119: posted_key = 0x57; break;
            case 97: posted_key = 0x41; break;
            case 115: posted_key = 0x53; break;
            case 100: posted_key = 0x44; break;
            case 32: posted_key = VK_SPACE; break;
        }

        if (posted_key == NULL) continue; // Key isn't W, A, S, D or SPACE

        if (!PostMessage(hndl, WM_KEYDOWN, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC)))
        { 
            print("Error while posting WM_KEYDOWN"); 
            break; 
        }

        if (!PostMessage(hndl, WM_CHAR, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) 
        { 
            print("Error while posting WM_CHAR"); 
            break; 
        }

        Sleep(100);
        if (!PostMessage(hndl, WM_KEYUP, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) 
        { 
            print("Error while posting WM_KEYUP"); 
            break; 
        }
    }

    return 0;
}

现在发布的消息具有不同的模式as you can see here。在字符代码为“119”的 3 条预期消息之间似乎张贴了字符代码为“83”的

WM_CHAR
消息。然后在
WM_KEYUP
消息之后额外的'119'字符代码消息。

至于我的程序行为,它不再突然退出表明

PostMessage
正在返回一个非零值。

然而,目标应用程序仍然表现得好像无限期地按下键一样。

c++ winapi keyboard-events sendkeys sendmessage
1个回答
0
投票

我认为如果您正确格式化代码,问题会变得很明显。

比较:

if (!PostMessage(hndl, WM_KEYDOWN, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) print("Error while posting WM_KEYDOWN"); break;

if (!PostMessage(hndl, WM_KEYDOWN, posted_key, MapVirtualKey(posted_key, MAPVK_VK_TO_VSC))) 
    print("Error while posting WM_KEYDOWN"); 
break;

提示:你可能需要一些花括号。

© www.soinside.com 2019 - 2024. All rights reserved.