【问题标题】:How to send continuous keypress to a program?如何将连续按键发送到程序?
【发布时间】:2011-10-02 15:45:20
【问题描述】:

我一直在使用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(全部 3 个都是十六进制)

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

通过只发送一个 WM_KEYDOWN 消息,效果是连续按下键。要停止程序作为键被连续按下,我必须按下键盘上的那个键并释放它,以便生成 WM_KEYUP。在代码中发送 WM_KEYUP 会给出 System.OverFlow “算术运算导致溢出”。例外。知道为什么会发生这种情况吗?

感谢您的回复:Ation 和 takrl

【问题讨论】:

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

标签: c# winforms console


【解决方案1】:

如果我做对了,你想模仿在应用程序中按下一个键的效果,然后一直按下它直到操作系统开始重复击键?如果是这样的话,像@Ation 建议的 API 方法就是要走的路。

但是,您应该使用 Spy++ 或类似工具来分析应用程序接收到的内容。对于操作系统重复的击键,我相信在实际释放密钥之前没有 WM_KEYUP 。而且我认为您无法通过使用SendKeys.SendSendKEys.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 上的fRepeat:1 和之前的所有WM_KEYDOWN,除了第一个,这似乎表示它是自动重复。

【讨论】:

    【解决方案2】:

    尝试将 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() 可以吗? (使应用程序无响应并不是很重要)
    猜你喜欢
    • 2014-04-06
    • 2011-07-19
    • 2012-08-22
    • 2022-10-19
    • 2013-12-11
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    相关资源
    最近更新 更多