【问题标题】:Keyboard input via SendInput (Win32 API) doesnt work, hardware one does通过 SendInput (Win32 API) 的键盘输入不起作用,硬件一做
【发布时间】:2015-11-15 22:46:32
【问题描述】:

我有一个任务,我需要在浏览器中显示的 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 的常见部分),但它的效果与硬件键盘一样好(输入了数字,更改了选择的值....),但没有生成任何消息。

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

非常感谢。

【问题讨论】:

标签: windows winapi browser input keyboard


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-12-21
    • 2010-11-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-06
    • 2020-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多