代码之家  ›  专栏  ›  技术社区  ›  Shane Miskin

是否有.NET替换GetAsyncKeyState?

  •  3
  • Shane Miskin  · 技术社区  · 18 年前

    在VB6中,我使用了对Windows API的调用, 获取异步密钥状态 ,以确定用户是否按了Esc键以允许他们退出长时间运行的循环。

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

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

    2 回复  |  直到 18 年前
        1
  •  3
  •   Franci Penov    18 年前

    您可以从中找到getAsyncKeyState的p/invoke声明 http://pinvoke.net/default.aspx/user32/GetAsyncKeyState.html

    这是C签名,例如:

    [DllImport("user32.dll")]
    static extern short GetAsyncKeyState(int vKey);
    
        2
  •  1
  •   Brian B.    18 年前

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

    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;
            }
        }
    
    }
    

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

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