Изменение символов на консоли в зависимости от нажатия клавиш пользователя - PullRequest
0 голосов
/ 01 февраля 2019

Я хочу изменить консоль в зависимости от того, что нажал пользователь.

Итак, у меня есть консоль с тремя вариантами, подобными этим:

>  Option 1

Option 2

Option 3

В основном,если пользователь нажимает стрелку вниз, консоль выглядит следующим образом:

Option 1

>  Option 2

Option 3

И если пользователь нажимает стрелку вверх, консоль возвращается в исходное состояние.

Я знаю, какчитать ввод пользователя с помощью Console.ReadKey (), но я не знаю, как изменить уже записанный вывод.

И последнее: когда пользователь нажимает клавишу ввода, консоль не создаетновая строка, но выбирает один из вариантов и вызывает делегата.

Ответы [ 2 ]

0 голосов
/ 01 февраля 2019

Вот аналогичный подход с чуть меньшим количеством кода, который скрывает курсор и показывает наш собственный курсор, который указывает выбранный пункт меню.

Метод принимает заголовок меню, список опций, которые пользователь может выбрать, и символ курсора.Он печатает заголовок и подчеркивание, а затем каждый параметр с 3 пробелами перед каждым.Затем мы перемещаем курсор к первому варианту (индекс строки 3, так как заголовок равен 0, подчеркивание равно 1, а пробел равен 2), второму символу и пишем символ возврата на одну позицию, за которым следует наш курсор (возврат на клавиатуре стирает первый символ так,мы можем написать новый).

Когда пользователь нажимает клавиши, мы обрабатываем только стрелки вверх и вниз и клавишу ввода.Передав 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;
        }
    }
}

Это можно проверить с помощью образца меню банкомата:

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

0 голосов
/ 01 февраля 2019

Этого не так уж сложно добиться, используя 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:
        ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...