Listen on ESC while reading Console line
Solution 1
You will probably have to forego the use of ReadLine
and roll your own using ReadKey
:
static void Main(string[] args)
{
Console.Clear();
Console.Write("Enter your name and press ENTER. (ESC to cancel): ");
string name = readLineWithCancel();
Console.WriteLine("\r\n{0}", name == null ? "Cancelled" : name);
Console.ReadLine();
}
//Returns null if ESC key pressed during input.
private static string readLineWithCancel()
{
string result = null;
StringBuilder buffer = new StringBuilder();
//The key is read passing true for the intercept argument to prevent
//any characters from displaying when the Escape key is pressed.
ConsoleKeyInfo info = Console.ReadKey(true);
while (info.Key != ConsoleKey.Enter && info.Key != ConsoleKey.Escape)
{
Console.Write(info.KeyChar);
buffer.Append(info.KeyChar);
info = Console.ReadKey(true);
}
if (info.Key == ConsoleKey.Enter)
{
result = buffer.ToString();
}
return result;
}
This code is not complete and may require work to make it robust, but it should give you some ideas.
Solution 2
A bit improved version of Chris Dunaway's one :
public static bool CancelableReadLine(out string value)
{
value = string.Empty;
var buffer = new StringBuilder();
var key = Console.ReadKey(true);
while (key.Key != ConsoleKey.Enter && key.Key != ConsoleKey.Escape)
{
if (key.Key == ConsoleKey.Backspace && Console.CursorLeft > 0)
{
var cli = --Console.CursorLeft;
buffer.Remove(cli, 1);
Console.CursorLeft = 0;
Console.Write(new String(Enumerable.Range(0, buffer.Length + 1).Select(o => ' ').ToArray()));
Console.CursorLeft = 0;
Console.Write(buffer.ToString());
Console.CursorLeft = cli;
key = Console.ReadKey(true);
}
else if (Char.IsLetterOrDigit(key.KeyChar) || Char.IsWhiteSpace(key.KeyChar))
{
var cli = Console.CursorLeft;
buffer.Insert(cli, key.KeyChar);
Console.CursorLeft = 0;
Console.Write(buffer.ToString());
Console.CursorLeft = cli + 1;
key = Console.ReadKey(true);
}
else if (key.Key == ConsoleKey.LeftArrow && Console.CursorLeft > 0)
{
Console.CursorLeft--;
key = Console.ReadKey(true);
}
else if (key.Key == ConsoleKey.RightArrow && Console.CursorLeft < buffer.Length)
{
Console.CursorLeft++;
key = Console.ReadKey(true);
}
else
{
key = Console.ReadKey(true);
}
}
if (key.Key == ConsoleKey.Enter)
{
Console.WriteLine();
value = buffer.ToString();
return true;
}
return false;
}
}
I didn't test it much, but at least works for me.
Related videos on Youtube
AstronAUT
Updated on September 15, 2022Comments
-
AstronAUT over 1 year
I want to read an users input into a string while still reacting on ESC press at any time, but without defining a system wide hotkey.
So when the user types e. g. "Test Name" but instead of confirming with ENTER presses ESC he should be led back into main menu.
Console.Write("Enter name: ") if (Console.ReadLine().Contains(ConsoleKey.Escape.ToString())) { goto MainMenu; } return Console.ReadLine();
Thats the simplest way I could think of, but since ESC is not seen by
Console.ReadLine()
it is not working.Found a rather complex way to react on ESC when pressed before starting to enter text here, but I want it to work at any time.
-
AstronAUT over 8 yearsThat is not working for me: when the while loop is entered
Console.ReadLine()
is stoping the thread until ENTER is pressed. -
AstronAUT over 8 yearsThank you for your response. Looks more efficient than mine, although I had to add support for backspace ;)
-
derekantrican almost 7 yearsThis doesn't seem to work with the backspace key. It moves the cursor back, but doesn't delete the letter