在VB6中,我使用了对Windows API的调用, GetAsyncKeyState ,以确定用户是否已按ESC键以允许它们退出长时间运行的循环。
Declare Function GetAsyncKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer
纯.NET中是否存在需要直接调用API的等效项?
答案 0 :(得分:3)
您可以从http://pinvoke.net/default.aspx/user32/GetAsyncKeyState.html
找到GetAsyncKeyState的P / Invoke声明以下是C#签名:
[DllImport("user32.dll")]
static extern short GetAsyncKeyState(int vKey);
答案 1 :(得分:1)
根据您的需要,有几个选项,包括调用与上述相同的方法。 从控制台应用程序:
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);
}