Intereting Posts
Извлеките строку подключения базы данных SQL Azure, которая связана с веб-сайтом Windows Azure с C # .NET. Какова концепция создания экземпляра classа с использованием имени интерфейса? Не удается записать в реестр под HKEY_LOCAL_MACHINE \ Software Доступ к Systray Запись атрибута CompareTo DataAnnotation Как нарисовать гистограмму с помощью EmguCV и C # Существует ли Enum для заказа Asc или Desc в .NET? Как я могу использовать два элемента управления progressBar для отображения каждого процесса загрузки файлов, а также общий ход загрузки всех файлов? Текст кнопки DataGridView не появляется, несмотря на то, что UseColumnTextForButtonText установлен в true Синтаксис BeginInvoke диспетчера Nullable type in x: TypeArguments ASP.NET MVC C # Получить имя controllerа и действия в classе передача объекта подключения DB к методам GetRequestStream () исключает тайм-аут при отправке данных на HTTPS-url Невозможно отладить приложение в режиме выпуска даже с DebugType = full

Перехват 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()); ... }