【问题标题】:How to push a key and release it using C#?如何使用 C# 按下一个键并释放它?
【发布时间】:2010-09-15 09:36:48
【问题描述】:

我正在编写一个 C# 程序,该程序从外部设备捕获信号,并将击键发送到另一个应用程序。我正在使用 SendKeys,它工作正常。

SendKeys 通过立即按住并释放某个键来“按下”它。我想让它按键随意释放。

我的问题是:“有没有办法向键发送“推”信号,然后在一定时间后发出“释放”信号?”

我不确定 SendKeys 是否能够做到这一点。有什么线索吗?

【问题讨论】:

    标签: c# keyboard


    【解决方案1】:

    我认为不可能直接从 .NET 您可以尝试通过 p/invoking 此处描述的函数来使用 keybd_event 本地调用:http://pinvoke.net/default.aspx/user32.keybd_event

    keybd_event 的 MSDN 在这里:http://msdn.microsoft.com/en-us/library/ms646304(VS.85).aspx

    希望有帮助!

    【讨论】:

      【解决方案2】:

      接受的答案使用已弃用的keybd_event。官方 API 现在是 SendInputhttp://inputsimulator.codeplex.com 也有一个很好的包装器。

      然而,以上都不能完全满足“钥匙持有”的情况。这是因为持有密钥会生成多条WM_KEYDOWN 消息,然后在发布时生成一条WM_KEYUP 消息(您可以使用Spy++ 进行检查)。

      WM_KEYDOWN 消息的频率取决于硬件、BIOS 设置和几个 Windows 设置:KeyboardDelayKeyboardSpeed。后者可从 Windows 窗体(SystemInformation.KeyboardDelaySystemInformation.KeyboardSpeed)访问。

      使用前面提到的输入模拟器库,我实现了一个模拟实际行为的键持有方法。 await/async 已准备就绪,并且支持取消。

      static Task SimulateKeyHold(VirtualKeyCode key, int holdDurationMs, 
                                  int repeatDelayMs, int repeatRateMs, CancellationToken token)
      {
          var tcs = new TaskCompletionSource<object>();
          var ctr = new CancellationTokenRegistration();
          var startCount = Environment.TickCount;
          Timer timer = null;
          timer = new Timer(s =>         
          {
              lock (timer)
              {
                  if (Environment.TickCount - startCount <= holdDurationMs)
                      InputSimulator.SimulateKeyDown(key);
                  else if (startCount != -1)
                  { 
                      startCount = -1; 
                      timer.Dispose();
                      ctr.Dispose();                    
                      InputSimulator.SimulateKeyUp(key);
                      tcs.TrySetResult(null);
                  }
              }
          });
          timer.Change(repeatDelayMs, repeatRateMs);
      
          if (token.CanBeCanceled)
              ctr = token.Register(() =>
                             {
                                 timer.Dispose();
                                 tcs.TrySetCanceled();
                             });
          return tcs.Task;
      }
      

      【讨论】:

      • 非常感谢您的宝贵意见。
      【解决方案3】:

      您可以使用 SendInput 或 keyb_event,它们都是原生 API 函数。 SendInput 比 keybd_event 有一些优势,但 SendInput 仅在 XP 开始可用。

      这里是msdn链接 http://msdn.microsoft.com/en-us/library/ms646310.aspx

      希望对你有帮助

      【讨论】:

        【解决方案4】:

        我曾经想在 powerpoint 上做同样的事情,隐藏光标,然后停止幻灯片。但这既困难又棘手,因为 powerpoint 中出现了许多顶级窗口,而且如果它不起作用,也很难确定仿真的哪个部分失败。在使用 Spy++ 查看消息队列后,我注意到加速器命令是在按键之后发送的,所以我模拟了加速器命令,它的工作原理就像魅力一样。所以你可能想研究这样的替代方案。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-08
          • 1970-01-01
          • 2011-10-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多