【问题标题】:Is there .Net replacement for GetAsyncKeyState?GetAsyncKeyState 是否有 .Net 替代品?
【发布时间】:2010-09-13 03:14:51
【问题描述】:

在 VB6 中,我使用了对 Windows API GetAsyncKeyState 的调用来确定用户是否按下了 ESC 键以允许他们退出长时间运行的循环。

Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer

纯 .NET 中是否存在需要直接调用 API 的等效项?

【问题讨论】:

    标签: .net winapi api keyboard


    【解决方案1】:

    您可以从http://pinvoke.net/default.aspx/user32/GetAsyncKeyState.html 找到 GetAsyncKeyState 的 P/Invoke 声明

    以下是 C# 签名示例:

    [DllImport("user32.dll")]
    static extern short GetAsyncKeyState(int vKey);
    

    【讨论】:

      【解决方案2】:

      根据您想要的用途,有几个选项,包括调用与上述相同的方法)。 从控制台应用程序:

      bool exitLoop = false;
      for(int i=0;i<bigNumber && !exitLoop;i++)
      {
          // Do Stuff.
          if(Console.KeyAvailable)
          {
              // Read the key and display it (false to hide it)
              ConsoleKeyInfo key = Console.ReadKey(true);
              if(ConsoleKey.Escape == key.Key)
              {
                  exitLoop=false;
              }
          }
      }
      

      如果您正在处理 Windows 窗体,则每个窗体都有许多关键相关事件,您可以根据需要侦听和处理(简化了大部分逻辑):

      public partial class Form1 : Form
      {
          private bool exitLoop;
          public Form1()
          {
              InitializeComponent();
              this.KeyUp += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyUp);
          }
          public void doSomething()
          {
              // reset our exit flag:
              this.exitLoop = false;
              System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(delegate(object notUsed)
                  {
                      while (!exitLoop)
                      {
                          // Do something
                      }
                  }));
          }
          private void Form1_KeyUp(object sender, KeyEventArgs e)
          {
              if (Keys.Escape == e.KeyCode)
              {
                  e.Handled = true;
                  this.exitLoop = true;
              }
          }
      
      }
      

      请注意,这是非常简化的 - 它不处理任何常见的线程问题或类似问题。正如 cmets 中所指出的,最初的解决方案并没有解决这个问题,我添加了一个快速的小 ThreadPool 调用来线程化后台工作。另请注意,侦听关键事件的问题在于其他控件实际上可能会处理它们,因此您需要确保在正确的控件上注册事件。如果一个 Windows 窗体应用程序是你前进的方向,你也可以尝试将自己注入到消息循环本身......

      public override bool PreProcessMessage(ref Message msg)
      {
        // Handle the message or pass it to the default handler...
        base.PreProcessMessage(msg);
      }
      

      【讨论】:

      • 我认为这不会起作用,因为 KeyUp 事件不会在“doSomething”循环运行时触发。
      猜你喜欢
      • 2021-02-25
      • 2015-05-02
      • 2013-08-23
      • 2017-03-25
      • 1970-01-01
      • 2013-01-29
      • 2011-01-19
      • 2020-06-11
      • 1970-01-01
      相关资源
      最近更新 更多