通过SendInput(Win32 API)输入的键盘不起作用,硬件也可以

时间:2015-08-21 21:38:33

标签: windows winapi browser input keyboard

我有一个任务,我需要在浏览器中显示的网页表单上点击鼠标,并且还要做一些键盘输入,在文本框中填入数字或按下箭头的顺序,以便在组合中进行选择框。

我有窗口处理程序,坐点也是点击,它对我来说很好(非常简单的功能):

 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的常用部分)时,它的功能与硬件键盘一样好(数字已输入,所选值已更改....),但不会生成任何消息。

知道如何模拟硬件击键并将序列放在我需要的地方吗?

非常感谢。

1 个答案:

答案 0 :(得分:4)

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() vs 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));
}