将单元素数组传递给SendInput是一个错误吗?

时间:2017-10-14 13:03:47

标签: winapi sendinput

给出以下代码

void foo() {
    INPUT input{};
    input.type = INPUT_MOUSE;
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
    SendInput(1, &input, sizeof(input));
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
    SendInput(1, &input, sizeof(input));
};

在连续调用中将单元素数组传递给SendInput是一个错误吗?这似乎得到了文档的完美支持。

1 个答案:

答案 0 :(得分:9)

简答:也许。

更长的答案:这取决于。

要了解它所依赖的内容,以及何时重要,请了解为什么SendInput被引入Windows API:为此,它整合了keybd_eventmouse_event将API转换为单个API调用。更重要的是,它增加了以前调用无法使用的重要功能。这在文档中提到:

  

SendInput 函数将INPUT结构中的事件串行插入键盘或鼠标输入流。 用户(使用键盘或鼠标)或通过拨打keybd_eventmouse_event或其他来电插入的其他键盘或鼠标输入事件中没有穿插这些事件到 SendInput

换句话说:SendInput建立注入输入序列的原子性,而不管调用代码控制之外的外部事件。

当输入由一系列单个事件组成时,原子注入输入通常很重要,如问题中所示。代码注入一个鼠标按钮,然后通过鼠标按钮向两个单独调用SendInput。虽然目的是只有一个鼠标单击事件,但实现允许其他输入源散布输入。当另一个输入源在鼠标按钮向下和向上事件之间产生鼠标移动事件时,预期的点击已变为拖放操作。不是在文件资源管理器中选择文件,而是将相同的代码抛出到回收站中。这显然构成了一个错误。

同样,注入由键组合组成的键盘输入通常需要原子性保证。注入 Ctrl + C 要求所有四个输入事件都在一个事务中。否则,(恶意)输入源可以在 Ctrl 键之后立即合成 Ctrl 键启动事件,使代码注入 C ,使用迷路 Ctrl 键上事件尾随。这可能不是我想要的。

总结:重复调用SendInput是一个错误,如果满足以下条件,则将1作为第一个参数传递:

  • 输入包含一系列单独的输入事件。
  • 需要将输入解释为单个单元。