8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

当 Console.ReadKey 在 C# 中接收到 Esc 键时,如何修复控制台输出?

Thai Anh Duc 1月前

35 0

我想从针对 .NET Core 3.1 的 C# 控制台应用程序读取用户输入。在某些情况下,用户可以选择按 Es 来取消输入和相关操作……

我想从针对 .NET Core 3.1 的 C# 控制台应用程序读取用户输入。在某些情况下,用户可以选择 在提示用户输入时随时 Esc

以下脚本适用于空字符串(用户只需按 Enter 而不执行任何其他操作)和正常用户输入(用户输入字符并用 Enter )。

但有一个问题:当用户取消输入(按 Esc )时,后面的第一个字符 Console.WriteLine 将被抑制,并且 Console.Write 不会输出任何内容。观察表明,必须输出换行符才能恢复 Console.WriteLine 预期 Console.Write 行为。

与此直接相关的另一个问题是,当我注入额外的换行符时,在正常输入的情况下,我会收到 2 个换行符,而在取消输入的情况下,我会收到 1 个换行符。

using System;
using System.Text;
using System.Text.RegularExpressions;

namespace ConsoleApp1
{
    internal class Program
    {
        internal const ConsoleColor DefaultConsoleForegroundColor = ConsoleColor.Gray;
        internal const ConsoleColor DefaultConsoleInputForegroundColor = ConsoleColor.White;

        internal static readonly Regex WhitespaceRegex = new Regex(@"\s{2,}", RegexOptions.Compiled | RegexOptions.CultureInvariant);

        internal static readonly Encoding UTF8NoBomEncoding = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: false);

        private static void Main()
        {
            Console.InputEncoding = UTF8NoBomEncoding;
            Console.OutputEncoding = UTF8NoBomEncoding;
            Console.Title = @"ConsoleApp1";
            Console.TreatControlCAsInput = true;
            Console.Clear();
            Console.ResetColor();
            Console.ForegroundColor = DefaultConsoleForegroundColor;

            string firstName = ConsoleReadLine(message: @"Enter your first name: ", treatEmptyOrWhitespaceAsNull: true) ?? @"World";
            Console.WriteLine(@"Hello, {0}!", firstName);

            ConsoleReadKey(message: @"Press any key to exit...", hideInput: true, messageColor: DefaultConsoleInputForegroundColor);
        }

        internal static string ConsoleReadLine(string message = null, bool hideInput = false, bool treatEscapeAsCancel = true,
                                               bool trimInput = true, bool normalizeWhitespace = true,
                                               bool treatEmptyOrWhitespaceAsNull = false, bool addLineBreak = true,
                                               ConsoleColor messageColor = DefaultConsoleForegroundColor,
                                               ConsoleColor inputColor = DefaultConsoleInputForegroundColor)
        {
            string inputString;

            // Print optional message before the prompt (same line).
            Console.ForegroundColor = messageColor;
            if (!string.IsNullOrWhiteSpace(message))
                Console.Write(message);

            // Get input from user.
            Console.ForegroundColor = inputColor;
            StringBuilder inputBuilder = new StringBuilder();
            while (true)
            {
                ConsoleKeyInfo inputKey = Console.ReadKey(hideInput);
                if (inputKey.Key == ConsoleKey.Enter)
                {
                    inputString = inputBuilder.ToString();
                    break;
                }
                else if (treatEscapeAsCancel && inputKey.Key == ConsoleKey.Escape)
                {
                    inputString = null;
                    break;
                }
                else
                    inputBuilder.Append(inputKey.KeyChar);
            }

            // Optional input modifications.
            if (inputString != null)
            {
                if (trimInput)
                    inputString = inputString.Trim();
                if (normalizeWhitespace)
                    WhitespaceRegex.Replace(inputString, @" ");
                if (treatEmptyOrWhitespaceAsNull && string.IsNullOrWhiteSpace(inputString))
                    inputString = null;
            }

            // Reset foreground color.
            Console.ForegroundColor = DefaultConsoleForegroundColor;

            if (addLineBreak)
                Console.WriteLine();

            return inputString;
        }

        internal static ConsoleKeyInfo ConsoleReadKey(string message = null, bool hideInput = false, bool addLineBreak = true,
                                                      ConsoleColor messageColor = DefaultConsoleForegroundColor,
                                                      ConsoleColor inputColor = DefaultConsoleInputForegroundColor)
        {
            ConsoleKeyInfo key;

            // Print optional message before the prompt (same line).
            Console.ForegroundColor = messageColor;
            if (!string.IsNullOrWhiteSpace(message))
                Console.Write(message);

            // Get input from user.
            Console.ForegroundColor = inputColor;
            key = Console.ReadKey(hideInput);

            // Reset foreground color.
            Console.ForegroundColor = DefaultConsoleForegroundColor;

            if (addLineBreak)
                Console.WriteLine();

            return key;
        }
    }
}

回想几年前(“过去”),由于控制字符也已提交,我不得不两次/三次读取键盘输入。但是,在 注册 Esc

如何解决与按下 Esc 键相关的输入取消问题?


例 1( 正确 )

Enter your first name: Test<Enter>
Hello, Test!
Press any key to exit...

示例 2( 错误 )

Enter your first name: Test<Escape>
ello, World!
Press any key to exit...

例 3( 正确 )

Enter your first name: <Enter>
Hello, World!
Press any key to exit...

例4( 错误 )

Enter your first name: <Escape>
ello, World!
Press any key to exit...
帖子版权声明 1、本帖标题:当 Console.ReadKey 在 C# 中接收到 Esc 键时,如何修复控制台输出?
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Thai Anh Duc在本站《.net》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 感谢@jscarle,解决方案是不允许 Console.ReadKey 打印字符,而是手动执行。

    这是修复该功能的代码 ConsoleReadLine

    while (true)
    {
        ConsoleKeyInfo inputKey = Console.ReadKey(true);
        if (inputKey.Key == ConsoleKey.Enter)
        {
            inputString = inputBuilder.ToString();
            break;
        }
        else if (treatEscapeAsCancel && inputKey.Key == ConsoleKey.Escape)
        {
            inputString = null;
            break;
        }
        else
            inputBuilder.Append(inputKey.KeyChar);
    
        if (!hideInput)
            Console.Write(inputKey.KeyChar);
    }
    
  • 正常行为,您正在将转义字符打印到控制台,因此以下字符将被视为控制字符。您需要始终自己隐藏 Console.ReadKey 和 Console.Write 字符(转义字符除外)。

返回
作者最近主题: