Winapi 将单个元素数组传递给SendInput是一个bug吗?

Winapi 将单个元素数组传递给SendInput是一个bug吗?,winapi,sendinput,Winapi,Sendinput,给定以下代码 void foo(){ 输入{}; input.type=输入\鼠标; input.mi.dwFlags=MOUSEEVENTF_LEFTDOWN; SendInput(1,&input,sizeof(input)); input.mi.dwFlags=MOUSEEVENTF_LEFTUP; SendInput(1,&input,sizeof(input)); }; 在连续调用中将单个元素数组传递给对象是错误吗?这似乎得到了文档的完美支持。简短回答:可能吧 更长的回答:视情况而定

给定以下代码

void foo(){
输入{};
input.type=输入\鼠标;
input.mi.dwFlags=MOUSEEVENTF_LEFTDOWN;
SendInput(1,&input,sizeof(input));
input.mi.dwFlags=MOUSEEVENTF_LEFTUP;
SendInput(1,&input,sizeof(input));
};
在连续调用中将单个元素数组传递给对象是错误吗?这似乎得到了文档的完美支持。

简短回答:可能吧

更长的回答:视情况而定

为了了解它所依赖的是什么,当这很重要时,了解为什么要将和API引入Windows API将有助于理解:首先,它将和API合并到一个API调用中。更重要的是,它增加了一个重要的功能,这在以前的调用中是不可用的。这在文档中被称为:

SendInput函数将结构中的事件顺序插入键盘或鼠标输入流这些事件不会与用户(使用键盘或鼠标)插入的其他键盘或鼠标输入事件混杂在一起,也不会通过调用或其他调用SendInput插入

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

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

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

总而言之:如果满足以下条件,则反复调用
SendInput
,并将
1
作为第一个参数传递,这是一个错误:

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

这个答案只是不必要的冗长的文档排练。@VTT:是吗?不同意没有必要。或或事实上,随便挑一个
SendInput
问题,你就会发现,这个问答是非常必要的。它可以大大缩短,基本上是“如果你要发送一系列输入事件,而不想让其他事件介于两者之间,你必须通过一次调用
SendInput
发送整个文件包。”@VTT:这是一个供大家使用的问答网站。如果你认为你可以做得更好,那就继续提交你自己的答案。我已经反复检查了很多次,认为
SendInput
的原子性是完全错误的。如果在键自动重复时正确调用了
SendInput
(即,用户按住键),则自动重复键将与
SendInput
注入的字符混合。问题可以重命名为“如何正确发送带有SendInput的输入事件序列?”因为它本质上就是答案的全部。@VTT:是的,它可能是。但这不是被问到的问题。一次又一次被问到的问题是,在标题中。这里有一个问题。对于那些在这些问题上苦苦挣扎并寻求帮助的用户来说,问题标题应该更容易找到。我认为更通用的标题变体更容易发现。如果输入序列较长,则将
2
3
4
作为第一个参数传递也可能是一个潜在的错误。因此,关于传递
1
的标题太窄了。@VTT:那么他们在寻找一个不同的问题,而不是这个问题。@BoltClock似乎这个问题的重点是涵盖一个常见的情况,即当用户将输入序列发送分成几个
SendInput
调用时,
SendInput
误用。