拦截ESC而不从缓冲区中删除其他按键

我有一个控制台应用程序,提示用户输入多个。 我希望用户能够在任何提示取消操作后按下escape。

就像是:

if (Console.ReadKey().Key != ConsoleKey.Escape) { string input = Console.ReadLine(); ... } 

但问题是,如果按下除escape之外的键,它将不是输入的一部分(从ReadLine返回)。

有没有办法“偷看”下一个键,否则这样做?

 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] internal struct InputRecord { internal short eventType; internal KeyEventRecord keyEvent; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] internal struct KeyEventRecord { internal bool keyDown; internal short repeatCount; internal short virtualKeyCode; internal short virtualScanCode; internal char uChar; internal int controlKeyState; } [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool PeekConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead); [DllImport("kernel32.dll", SetLastError = true)] internal static extern bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead); [DllImport("kernel32.dll", SetLastError = true)] internal static extern IntPtr GetStdHandle(int nStdHandle); static Nullable PeekConsoleEvent() { InputRecord ir; int num; if (!PeekConsoleInput(GetStdHandle(-10), out ir, 1, out num)) { //TODO process error } if (num != 0) return ir; return null; } static InputRecord ReadConsoleInput() { InputRecord ir; int num; if (!ReadConsoleInput(GetStdHandle(-10), out ir, 1, out num)) { //TODO process error } return ir; } static bool PeekEscapeKey() { for (; ; ) { var ev = PeekConsoleEvent(); if (ev == null) { Thread.Sleep(10); continue; } if (ev.Value.eventType == 1 && ev.Value.keyEvent.keyDown && ev.Value.keyEvent.virtualKeyCode == 27) { ReadConsoleInput(); return true; } if (ev.Value.eventType == 1 && ev.Value.keyEvent.keyDown) return false; ReadConsoleInput(); } } 

用法示例:

  for (; ; ) { Console.Write("?"); if (PeekEscapeKey()) { Console.WriteLine("esc"); continue; } Console.Write(">"); var line = Console.ReadLine(); Console.WriteLine(line); } 

要窥视,您必须使用TextReader.Peek。 要在控制台中使用它,您可以使用Console.In.Peek() 。 要使用您正在考虑的代码:

 if(Console.In.Peek() != "\0x1B") // 0x1B is the Escape Key { string input = Console.ReadLine(); .... } 

这应该工作。 我没有测试过,但似乎没错。

或者用于比@ user823682稍微不那么优雅的方法

 ConsoleKeyInfo key = Console.ReadKey().Key; if (key != ConsoleKey.Escape) { string input = String.Concat(key.KeyChar,Console.ReadLine()); ... }