根据用户击键在控制台上更改字符

时间:2019-01-31 22:04:32

标签: c# console

我要做的是根据用户的按下来更改控制台。

所以我有一个带有以下三个选项的控制台:

>  Option 1

Option 2

Option 3

基本上,如果用户按下向下箭头,则控制台将变为:

Option 1

>  Option 2

Option 3

如果用户按下向上箭头,则控制台将返回到其初始状态。

我知道如何使用Console.ReadKey()读取用户的输入,但是我不知道如何修改已经写入的输出。

最后一件事是,当用户按下Enter键时,控制台不会创建新行,而是选择其中一个选项并调用委托。

2 个答案:

答案 0 :(得分:1)

使用Console.ReadKey和一些变量来保存所选选项的状态并不难。

以下代码是您所寻找的东西的非常快速和懒惰的实现。花一些时间自己重新编写它-这是让您了解如何实现所需的功能。

static void Main(string[] args)
{
    bool IsRunning = true;
    int Selected = 1;

    while (IsRunning)
    {
        ConsoleKeyInfo NextKey = new ConsoleKeyInfo();

        if (Selected < 1)
            Selected = 3;
        else if (Selected > 3)
            Selected = 1;

        Console.Clear();
        if (Selected == 1)
            Console.Write("> ");
        Console.WriteLine("Option 1");
        Console.WriteLine();
        if (Selected == 2)
            Console.Write("> ");
        Console.WriteLine("Option 2");
        Console.WriteLine();
        if (Selected == 3)
            Console.Write("> ");
        Console.WriteLine("Option 3");
        Console.WriteLine();
        Console.Write("Choose an option (Q to Quit): ");

        while (!(NextKey.Key == ConsoleKey.DownArrow ||
                NextKey.Key == ConsoleKey.UpArrow ||
                NextKey.Key == ConsoleKey.Q ||
                (NextKey.KeyChar >= '1' &&
                NextKey.KeyChar <= '3')))
        {
            NextKey = Console.ReadKey();
        }

        switch (NextKey.Key)
        {
            case ConsoleKey.D1:
                // Do something
                break;

            case ConsoleKey.D2:
                // Do something
                break;

            case ConsoleKey.D3:
                // Do something
                break;

            case ConsoleKey.DownArrow:
                Selected++;
                break;

            case ConsoleKey.UpArrow:
                Selected--;
                break;

            case ConsoleKey.Q:
                IsRunning = false;
                break;
        }
    }
}

在没有按'Q'键退出应用程序的情况下,代码将循环播放。

按下向下或向上箭头将在可用选项中旋转。

按1、2或3时,将使// Do something语句内的switch行运行。您应该在这里为每个选项调用任何存在的功能。

为了使用所选选项更新“菜单”,请清除控制台输出,然后重新输出。通过Selected变量标识正确的选项。

还有其他几种方法可以实现上述目的,但更为简洁。我想给你一个从哪里开始的想法。我并不是说这是最好或最整洁的解决方案。

编辑

发生想法-您想使用Enter选择该选项。

我已经稍微修改了代码以提供该功能:

    while (!(NextKey.Key == ConsoleKey.DownArrow ||
            NextKey.Key == ConsoleKey.UpArrow ||
            NextKey.Key == ConsoleKey.Q ||
            NextKey.Key ==  ConsoleKey.Enter))
    {
        NextKey = Console.ReadKey();
    }

    switch (NextKey.Key)
    {
        case ConsoleKey.Enter:
            // Do something depending on Selected option
            switch (Selected)
            {
                case 1:
                    // Do something
                    break;

                case 2:
                    // Do something
                    break;

                case 3:
                    // Do something
                    break;
            }
            break;

        case ConsoleKey.DownArrow:
        ...

答案 1 :(得分:0)

这是一种类似的方法,只需要较少的代码,它隐藏了光标并显示了我们自己的指示所选菜单项的自定义光标。

该方法采用菜单标题,供用户选择的选项列表以及光标字符。它打印出页眉和下划线,然后打印每个选项,每个选项前带有3个空格。然后,将光标移动到第一个选项(第二行,因为标头为0,下划线为1,空格为2,所以行索引为3),第二个字符,然后写一个退格字符,后跟光标(退格删除了第一个字符,因此我们可以写一个新的。)

当用户按下键时,我们仅处理上下箭头和Enter键。通过将true传递到Console.ReadKey(),用户输入将被“丢弃”,并且不会显示在窗口中。这样一来,我们switch只能使用我们关心的键。

当他们按下箭头键时,我们将光标移动到当前行的第二列,先打印一个退格键,然后再打印一个空格(以擦除旧光标),然后上下移动一行,然后从第二列开始我们先打印退格键,然后再打印光标字符。

当用户按下Enter时,我们再次启用控制台光标,并返回光标所在的行以指示当时选择了哪个项目:

private static int GetMenuChoice(string header, List<string> options, char cursor = '>')
{
    // Clear console and hide cursor
    Console.Clear();
    Console.CursorVisible = false;

    // Write our header with an underline
    Console.WriteLine("   " + header);
    Console.WriteLine("   " + new string('-', header.Length));
    Console.WriteLine();

    // Write out each option with spaces before it
    options.ForEach(option => Console.WriteLine($"   {option}"));

    // Move to the first option and, from the second character,
    // write a backspace and then the cursor symbol
    Console.SetCursorPosition(1, 3);
    Console.Write($"\b{cursor}");

    // Move cursor when user presses arrow keys, and get selection when they press enter
    while (true)
    {
        // Pass 'true' to ReadKey so the input is not written
        var input = Console.ReadKey(true);

        switch (input.Key)
        {
            case ConsoleKey.UpArrow:
                if (Console.CursorTop > 3)
                {
                    Console.CursorLeft = 1;
                    Console.Write("\b ");
                    Console.SetCursorPosition(1, Console.CursorTop - 1);
                    Console.Write($"\b{cursor}");
                }
                break;

            case ConsoleKey.DownArrow:
                if (Console.CursorTop < options.Count + 2)
                {
                    Console.CursorLeft = 1;
                    Console.Write("\b ");
                    Console.SetCursorPosition(1, Console.CursorTop + 1);
                    Console.Write($"\b{cursor}");
                }
                break;

            case ConsoleKey.Enter:
                var selection = Console.CursorTop - 3;
                Console.CursorVisible = true;
                Console.SetCursorPosition(0, options.Count + 4);
                return selection;
        }
    }
}

这可以通过示例ATM菜单进行测试:

private static void Main()
{
    var options = new List<string>
    {
        "Open a new account",
        "Deposit Money",
        "Withdraw money",
        "Check balance",
        "Exit"
    };

    var selectedItem = GetMenuChoice("ATM Machine", options);

    Console.WriteLine($"You selected option: '{options[selectedItem]}'");

    GetKeyFromUser("\nDone! Press any key to exit...");
}

输出

enter image description here