如何向程序发送连续的按键?

6
我一直在使用SendKeys.Send()SendKeys.SendWait()向前台程序(不同于编写的应用程序)发送按键信息。我尝试通过反复发送同一个键并设置延迟时间来发送连续按键,但在该应用程序中其效果与真正连续按键并不相同。我的问题是:如何向程序发送连续按键?这个按键的效果必须与我在该应用程序内按下该键时一样。

解决方案编辑

解决方案是调用方法:

[DllImport("User32.dll")]
static extern int SendMessage(IntPtr hWnd, uint wMsg, UIntPtr wParam, IntPtr lParam);

使用从以下参数获得的:

public System.Diagnostics.Process[] p = System.Diagnostics.Process.GetProcessesByName("process");

p [0] .MainWindowHandle 是 hWnd

并在窗口上使用 Spy:

在 Spy 中右键单击消息行会显示wMsgwParamlParam(全部为十六进制)

SendMessage(p[0].MainWindowHandle, (uint)0x0100, (UIntPtr)0x00000041, (IntPtr)(0x001E0001));

仅发送一个 WM_KEYDOWN 消息即可使效果连续按下键。要停止程序作为键被连续按下的操作,我必须按下并释放键盘上的该键,以生成 WM_KEYUP。在代码中发送 WM_KEYUP 会导致 System.OverFlow "算术运算导致溢出" 异常。有什么想法为什么会发生这种情况吗?

感谢您的回复:Ation 和 takrl


为什么你需要这样做?也许如果你解释一下这是为什么需要的,会有所帮助。 - takrl
2
为什么有人投票关闭?“如何发送连续按键”是一个完全可以接受的问题。 - user47589
@takrl: 我写了一个基于语音识别发送命令到游戏的程序,现在我想添加一个语音命令来向前走,但是重复发送按键无效。这就是为什么我想要发送一个连续的按键。 - Răzvan Flavius Panda
@Inuyasha:感谢您的支持(Shippo也同意我想):) 我真的不明白为什么有人想关闭一个以前没有回答过的有用问题。 - Răzvan Flavius Panda
@Inu 我猜它被投票关闭是因为不清楚 @Răzvan 到底想做什么。我认为他的评论让这一点更加清晰(请参见我的答案),除非我误解了... - takrl
@takrl:是的,你说得对,我需要编辑一下让它更清晰,“前台程序”这个词有点模糊。 - Răzvan Flavius Panda
2个回答

3
尝试使用Win API的SendMessage,并使用WM_KEYDOWN和WM_KEYUP进行消息发送。这些消息之间需要适当的延迟。您也可以使用PostMessage进行异步发送。
[DllImport("User32.dll")]
            public static extern int SendMessage(IntPtr hWnd, uint msg, int wparam, int lparam);

谢谢,我今晚会测试这个。我应该如何在消息之间实现延迟?Thread.Sleep()可以吗?(使应用程序无响应并不是非常重要) - Răzvan Flavius Panda

2
如果我理解正确,您想要模拟在应用程序中按下键盘并将其保持按下状态,直到操作系统开始重复击键的效果? 如果是这样,像@Ation建议的API方法是正确的方法。

然而,您应该使用类似于Spy ++之类的工具来分析应用程序接收到的内容。 对于操作系统重复击键,我认为在实际释放键之前没有WM_KEYUP。 而且我不认为您可以通过使用{{link1:SendKeys.Send}}或{{link2:SendKEys.SendWait}}来复制此行为。

编辑

这是一个Spy ++日志摘录,当按下字母A时,它被采取了TextBox控件:

<00168> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00173> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:0 fUp:0
<00182> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00187> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00196> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:3 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00201> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:3 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00210> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:4 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00215> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:4 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00224> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:3 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00229> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:3 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00238> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:4 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00243> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:4 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00252> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:3 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00257> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:3 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00266> 00010590 P WM_KEYDOWN nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00271> 00010590 P WM_CHAR chCharCode:'97' (97) cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:0
<00280> 00010590 P WM_KEYUP nVirtKey:'A' cRepeat:1 ScanCode:1E fExtended:0 fAltDown:0 fRepeat:1 fUp:1

如您所见,有几个 WM_KEYDOWN 事件后跟着一个 WM_CHAR 事件(这可能只适用于我用来测试的 TextBox,对于其他应用或控件则不确定),并在最后有一个 WM_KEYUP 事件。日志中有许多其他看似与按键无关的信息(它们是连续编号的),但这可能因您使用的应用程序或控件而有所不同。
请注意,WM_KEYUP 和所有之前的 WM_KEYDOWN(除了第一个)上都有 fRepeat:1,这似乎表示这是自动重复触发的按键事件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接