【问题标题】:Issue with WinAPI SendInput codeWinAPI SendInput 代码问题
【发布时间】:2012-05-29 10:47:56
【问题描述】:

我正在编写一个程序,到目前为止一切顺利,但是我对以下代码有疑问:

void Send(string content) {
    unsigned int size = content.size();
    INPUT *inputs = new INPUT[size];

    for (unsigned int i = 0; i < size; i++) {
        inputs[i].type = 1;
        inputs[i].ki.wVk          = 0;//LOWORD(VkKeyScan(content.at(i)));
        inputs[i].ki.wScan        = content.at(i);
        inputs[i].ki.dwFlags      = KEYEVENTF_UNICODE | KEYEVENTF_SCANCODE;
        inputs[i].ki.time         = 0;
        inputs[i].ki.dwExtraInfo  = ::GetMessageExtraInfo();
    }

    SendInput(size, inputs, sizeof(*inputs)*size);

    for (unsigned int i = 0; i < size; i++) {
        inputs[i].ki.dwFlags &= KEYEVENTF_KEYUP;
    }

    SendInput(size, inputs, sizeof(*inputs)*size);
}

我想要实现的是能够像这样发送输入:

Send(string("Hello World!"));

但是,它会做它不应该做的所有事情,例如移动光标,即使类型设置为键盘也是如此。最多输出一个字符。 正如你在第 2 行看到的,我有一个 INPUT 数组。但是,当我在调试器中查看它时,它只是显示为单个 INPUT 结构,而不是结构数组。

我正在使用带有 gdb 调试器 + Code::Blocks IDE 的 g++。

谢谢大家。

编辑

新代码:

void Send(string content) {
    unsigned int size = content.size();
    INPUT *inputs = new INPUT[size];
    INPUT curr[1];

    ZeroMemory(inputs, sizeof(*inputs)*size);

    for (unsigned int i = 0; i < size; i++) {
        inputs[i].type = 1;
        inputs[i].ki.wVk          = 0;//LOWORD(VkKeyScan(content.at(i)));
        inputs[i].ki.wScan        = content.at(i);
        inputs[i].ki.dwFlags      = KEYEVENTF_UNICODE | KEYEVENTF_SCANCODE;
        inputs[i].ki.time         = 0;
        inputs[i].ki.dwExtraInfo  = ::GetMessageExtraInfo();
    }

    for (unsigned int i = 0; i < size; i++) {
        curr[0] = inputs[i];            // Current input
        int a = ::SendInput(1, (INPUT*)&curr, sizeof(curr));

        inputs[i].ki.dwFlags &= KEYEVENTF_KEYUP;

        curr[0] = inputs[i];
        int b = ::SendInput(1, (INPUT*)&curr, sizeof(curr));

        TCHAR *buff = new TCHAR[3];

        wsprintf(buff, "%i %i", a, b);

        MessageBox(NULL, buff, "SendInput return vals", 0);
    }
}

这仍然没有发送任何内容。

【问题讨论】:

  • 现在你有无用的演员表。内存泄漏仍然存在。而且您正在超越 buff 并在此过程中破坏附近的内存。

标签: c++ winapi


【解决方案1】:
sizeof(*inputs)*size

这是错误的,cbSize 参数是一个 INPUT 结构的大小,而不是数组的总大小。

如果您没有丢弃 SendInput 返回值,您就会发现这一点。检查返回值是出现问题时可能进行的最基本的故障排除。

您还有内存泄漏。你应该在填充数组之前使用ZeroMemory

最后,您在释放任何一个键之前先按下所有键。如果你想输入文字,你应该按顺序按下并释放每个键,这样一次按下的键不超过一个。

【讨论】:

  • Ben,cbSize 不是错误——我更新了源代码。但是我会删除它。谢谢。 ZeroMemory 在整个阵列上一次?还是单独在每个索引上?你能解释一下你是怎么知道我有这个内存泄漏的吗?所以我需要先按下一个,然后释放一个,然后再继续?
  • 啊,我明白了。所以最后我只需要delete[] inputs?并且需要对INPUT* 进行强制转换,因为编译器出错了。
  • @Shane: ::SendInput(1, curr, sizeof curr); 应该可以工作,没有演员表。是的,delete [] inputs; 是正确的,尽管现在您添加了另一个分配。
  • curr 不是动态的,所以就内存泄漏而言应该不是问题?
【解决方案2】:

我想这是因为您只发送 KEYDOWN 消息。您可能想尝试先发送 KEYDOWN,然后再发送 KEYEVENTF_KEYUP 以获得相同的字符。

[编辑新代码]

一些提示:

  1. 移除 KEYEVENTF_SCANCODE
  2. string 用于 char 字符串,对于 UNICODE 使用 wstring
  3. 在测试您的功能之前,请确保某些带有编辑框的应用位于前台,例如记事本

【讨论】:

  • luskan,我现在已经实现了它,但是我没有成功。更新了代码。我仍然认为它与 INPUT 数组有关。
  • 我有记事本 :) 非常感谢 - 现在可以使用了!我不敢相信这是因为我没有使用 unicode。祝你有美好的一天!
猜你喜欢
  • 2020-04-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-09
  • 1970-01-01
  • 1970-01-01
  • 2017-04-23
  • 1970-01-01
相关资源
最近更新 更多