【问题标题】:Is it a bug to pass a single-element array to SendInput?将单元素数组传递给 SendInput 是否是错误?
【发布时间】:2018-03-26 11:22:47
【问题描述】:

给定以下代码

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 是否存在错误?文档似乎完全支持这一点。

【问题讨论】:

  • 问题可以重命名为“如何使用 SendInput 正确发送一系列输入事件?”因为它本质上就是答案的全部意义所在。
  • @VTT:是的,它可能是。但这不是被问到的问题。被一遍又一遍地问到的问题就是标题中的那个问题。这是reference
  • 对于遇到此类问题并寻求帮助的用户来说,应该更容易找到问题标题。我认为更通用的标题变体会更容易被发现。如果输入序列应该更长,则传递 234 作为第一个参数也可能是一个潜在的错误。所以标题只是通过1 太窄了。
  • @VTT:那么他们正在寻找一个不同的问题,而不是这个。
  • @BoltClock 看来这个问题的重点是要涵盖SendInput 滥用的常见 案例,当用户将输入序列发送拆分为多个SendInput 调用时。

标签: winapi sendinput


【解决方案1】:

简短回答:也许。

更长的答案:视情况而定。

要了解它依赖于什么,以及何时重要,有助于理解为什么将 SendInput 引入 Windows API:一方面,它将 keybd_eventmouse_event API 整合到一个 API 调用中.更重要的是,它增加了一个重要的功能,这是以前的电话所没有的。这在文档中有所说明:

SendInput 函数将INPUT 结构中的事件串行插入到键盘或鼠标输入流中。 这些事件不会与用户(使用键盘或鼠标)或通过调用 keybd_eventmouse_event 或对 的其他调用插入的其他键盘或鼠标输入事件穿插发送输入

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

当输入由一系列单独的事件组成时,原子注入输入通常很重要,就像在问题中一样。该代码在对SendInput 的 2 次单独调用中注入一个鼠标按钮,然后是一个鼠标按钮。虽然意图是有一个鼠标单击事件,但该实现允许其他输入源散布输入。当另一个输入源在鼠标按钮按下和向上事件之间产生鼠标移动事件时,预期的单击已变成拖放操作。相同的代码没有在文件资源管理器中选择文件,而是将文件扔进了回收站。这显然构成了一个错误。

同样,注入由组合键组成的键盘输入通常需要原子性保证。注入 Ctrl+C 要求所有四个输入事件都在一个事务中。否则,(恶意)输入源可能会在 Ctrl 键按下后立即合成 Ctrl 键向上事件,从而使代码注入 C,带有杂散的 Ctrl 键向上事件尾随。这可能也不是本意。

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

  • 输入由一系列单独的输入事件组成。
  • 要求将输入解释为单个单元。

【讨论】:

  • 这个答案只是对文档进行不必要的冗长排练。
  • @VTT:是吗? This 不同意没有必要。或thisThisthisthis。事实上,随机选择任何SendInput问题,你就会发现,这个问答是非常需要的。
  • 它可以大大缩短,基本上“如果您正在发送一系列输入事件并且不希望其他事件介于两者之间,您必须通过一次调用发送整个包SendInput 。”
  • @VTT:这是一个面向所有人的问答网站。如果您认为自己可以做得更好,请继续提交您自己的答案。
  • 我已经检查并再次检查了很多次SendInput 的假定原子性是完全错误的。如果在自动重复键(即用户按住键)时正确调用了SendInput,则自动重复键将与SendInput注入的字符混合。
猜你喜欢
  • 1970-01-01
  • 2023-02-14
  • 2016-05-07
  • 2019-05-30
  • 2019-04-25
  • 2021-02-10
  • 1970-01-01
  • 2011-04-22
  • 1970-01-01
相关资源
最近更新 更多