键盘输入通过SendInput (Win32 API)不工作,硬件一个



我有一个任务,我需要把一些鼠标点击在浏览器中显示的web表单上,也做一些键盘输入,如用数字填充文本框或使按下箭头序列,以便在组合框中获得选择。

我有窗口处理程序,坐标在哪里点击,它对我来说很好(非常简单的函数):

 extern "C" __declspec(dllexport) void __stdcall PutSingleClick(unsigned hwnd, int x, int y)
{
    SendMessage(((HWND) hwnd), WM_LBUTTONDOWN, MK_LBUTTON, MAKELPARAM(x, y));
    SendMessage(((HWND) hwnd), WM_LBUTTONUP, MK_LBUTTON, MAKELPARAM(x, y));
}

当我尝试发送键盘输入时,问题出现了,例如通过调用:

extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
    INPUT ip;
    ip.type = INPUT_KEYBOARD;
    ip.ki.time = 0;
    ip.ki.wVk = 0;
    ip.ki.dwExtraInfo = 0;
    ip.ki.wScan = VK_DOWN;
    for(int i = 0; i < times; i++)
    {
        ip.ki.dwFlags = KEYEVENTF_SCANCODE;
        SendInput(1, &ip, sizeof(INPUT));
        ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
        SendInput(1, &ip, sizeof(INPUT));
    }
    ip.ki.dwFlags = KEYEVENTF_SCANCODE;
    ip.ki.wScan = VK_RETURN;
    SendInput(1, &ip, sizeof(INPUT));
    ip.ki.dwFlags = KEYEVENTF_SCANCODE | KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));
}

调用此函数后什么也没做,只在输入缓冲区中保留了奇怪的字符(在我的例子中是"´" [akcent, dead character])。

当我试图捕捉spy++发生的事情时,鼠标事件(点击)被正确地监视(当手动和由程序生成时),但键盘事件没有-无论是程序还是手动。

当我尝试实用程序屏幕键盘(Windows的常见部分),它的工作原理和硬件键盘一样好(数字被输入,选择的值被改变....),但没有消息生成。

任何想法如何模拟硬件按键和把序列在我需要的地方?

VK_DOWNVK_RETURN虚拟密钥,而不是扫描码。因此,当调用SendInput()时,使用ip.ki.wVk字段而不是ip.ki.wScan字段,并去掉KEYEVENTF_SCANCODE标志:

extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
    INPUT ip = {0};
    ip.type = INPUT_KEYBOARD;
    ip.ki.wVk = VK_DOWN;
    for(int i = 0; i < times; i++)
    {
        ip.ki.dwFlags = 0;
        SendInput(1, &ip, sizeof(INPUT));
        ip.ki.dwFlags = KEYEVENTF_KEYUP;
        SendInput(1, &ip, sizeof(INPUT));
    }
    ip.ki.dwFlags = 0;
    ip.ki.wVk = VK_RETURN;
    SendInput(1, &ip, sizeof(INPUT));
    ip.ki.dwFlags = KEYEVENTF_KEYUP;
    SendInput(1, &ip, sizeof(INPUT));
}

但是,您不应该像这样调用SendInput()来单独发送多个输入事件。它违背了使用SendInput()keybd_event()的目的,没有任何好处。相反,您应该使用数组将所有事件一次性发送到SendInput(),例如:

#include <vector>
extern "C" __declspec(dllexport) void __stdcall PutKeystrokeDown(int times)
{
    INPUT ip = {0};
    ip.type = INPUT_KEYBOARD;
    ip.ki.wVk = VK_DOWN;
    std::vector<INPUT> ips;
    ips.reserve((times*2)+2);
    for(int i = 0; i < times; i++)
    {
        ip.ki.dwFlags = 0;
        ips.push_back(ip);
        ip.ki.dwFlags = KEYEVENTF_KEYUP;
        ips.push_back(ip);
    }
    ip.ki.dwFlags = 0;
    ip.ki.wVk = VK_RETURN;
    ips.push_back(ip);
    ip.ki.dwFlags = KEYEVENTF_KEYUP;
    ips.push_back(ip);
    SendInput(ips.size(), &ips[0], sizeof(INPUT));
}

最新更新