是否有.Net替代GetAsyncKeyState?
时间:2020-03-06 14:43:38 来源:igfitidea点击:
在VB6中,我使用了对Windows API的调用GetAsyncKeyState,以确定用户是否按了ESC键以允许他们退出长时间运行的循环。
Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
在纯.NET中是否存在需要直接调用API的等效项?
解决方案
我们可以从http://pinvoke.net/default.aspx/user32/GetAsyncKeyState.html找到GetAsyncKeyState的P / Invoke声明。
例如下面的签名:
[DllImport("user32.dll")] static extern short GetAsyncKeyState(int vKey);
根据期望用途,有两种选择,包括调用与上述相同的方法。
从控制台应用程序:
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; } } }
请注意,这是非常简化的,它不能处理任何常见的线程问题或者类似问题。正如评论中指出的那样,最初的解决方法没有解决该问题,我添加了一个快速的ThreadPool小调用来对后台工作进行线程化。还要注意,侦听关键事件的问题是其他控件可能实际上会处理它们,因此我们需要确保在正确的控件上注册了该事件。如果Windows窗体应用程序是我们前进的方向,我们还可以尝试将自己注入到消息循环本身中。
public override bool PreProcessMessage(ref Message msg) { // Handle the message or pass it to the default handler... base.PreProcessMessage(msg); }