C# arrow key input for a console app

前端 未结 5 1202
一生所求
一生所求 2020-11-28 14:29

I have a simple console app written in C#. I want to be able to detect arrow key presses, so I can allow the user to steer. How do I detect keydown/keyup events with a con

相关标签:
5条回答
  • 2020-11-28 14:53

    I have the same issue that you and I found, here, an interesting post using tasks. The original post can be found here: C# Console Application - How do I always read input from the console?

    I have to emulate a PWM output through a Raspberry GPIO (using mono C#) to test a LCD backlight. With two simple keys I wanted to change the duty cycle (up/down) and an extra key to stop the program.

    I tried this (variables):

    static ConsoleKeyInfo key = new ConsoleKeyInfo();
    static int counter = 0;
    static int duty = 5; // Starts in 50%
    

    Main program:

    static void Main(string[] args)
    {
    // cancellation by keyboard string
        CancellationTokenSource cts = new CancellationTokenSource();
        // thread that listens for keyboard input
        var kbTask = Task.Run(() =>
        {
            while (true)
            {
                key = Console.ReadKey(true);
                if (key.KeyChar == 'x' || key.KeyChar == 'X')
                {
                    cts.Cancel();
                    break;
                }
                else if (key.KeyChar == 'W' || key.KeyChar == 'w')
                {
                    if (duty < 10)
                        duty++;
                    //Console.WriteLine("\tIncrementa Ciclo");
                    //mainAppState = StateMachineMainApp.State.TIMER;
                    //break;
                }
                else if (key.KeyChar == 'S' || key.KeyChar == 's')
                {
                    if (duty > 0)
                        duty--;
                    //Console.WriteLine("\tDecrementa Ciclo");
                    //mainAppState = StateMachineMainApp.State.TIMER;
                    // break;
                }
            }
        });
    
        // thread that performs main work
        Task.Run(() => DoWork(), cts.Token);
    
        string OsVersion = Environment.OSVersion.ToString();
        Console.WriteLine("Sistema operativo: {0}", OsVersion);
        Console.WriteLine("Menú de Progama:");
        Console.WriteLine(" W. Aumentar ciclo útil");
        Console.WriteLine(" S. Disminuir ciclo útil");
        Console.WriteLine(" X. Salir del programa");
    
        Console.WriteLine();
        // keep Console running until cancellation token is invoked
        kbTask.Wait();
    }
    
    static void DoWork()
    {
        while (true)
        {
            Thread.Sleep(50);
            if (counter < 10)
            {
                if (counter < duty)
                    Console.Write("─");
                    //Console.WriteLine(counter + " - ON");
                else
                    Console.Write("_");
                    //Console.WriteLine(counter + " - OFF");
                counter++;
            }
            else
            {
                counter = 0;
            }
        }
    }
    

    When it's needed to increment the duty cycle, pressing 'W' key makes that the main task changes the duty cycle variable (duty); the same thing with 'S' key to decrement. The program finishes when 'X' key is pressed.

    0 讨论(0)
  • 2020-11-28 15:03
    System.Console.ReadKey(true).Key == ConsoleKey.UpArrow
    

    You could put that into a spin, something like:

    while(Running)
    {
      DoStuff();
      System.Console.ReadKey(true).Key == ConsoleKey.UpArrow
      Thread.Sleep(1)
    }
    
    0 讨论(0)
  • 2020-11-28 15:03

    you can do this

    bool keyWasPressed = false;
    if (consolekey.avalable)
    {
    keyvar = console.readkey(true);
    keyWasPressed = true;
    }
    if(keyWasPressed)
    {
    //enter you code here using keyvar
    }
    else
    {
    //the commands that happen if you don't press anything
    }
    
    0 讨论(0)
  • 2020-11-28 15:12

    A bit late now, but here's how to access keyboard state in a console application.

    Note that it's not all managed code as it requires GetKeyState to be imported from User32.dll.

    /// <summary>
    /// Codes representing keyboard keys.
    /// </summary>
    /// <remarks>
    /// Key code documentation:
    /// http://msdn.microsoft.com/en-us/library/dd375731%28v=VS.85%29.aspx
    /// </remarks>
    internal enum KeyCode : int
    {
        /// <summary>
        /// The left arrow key.
        /// </summary>
        Left = 0x25,
    
        /// <summary>
        /// The up arrow key.
        /// </summary>
        Up,
    
        /// <summary>
        /// The right arrow key.
        /// </summary>
        Right,
    
        /// <summary>
        /// The down arrow key.
        /// </summary>
        Down
    }
    
    /// <summary>
    /// Provides keyboard access.
    /// </summary>
    internal static class NativeKeyboard
    {
        /// <summary>
        /// A positional bit flag indicating the part of a key state denoting
        /// key pressed.
        /// </summary>
        private const int KeyPressed = 0x8000;
    
        /// <summary>
        /// Returns a value indicating if a given key is pressed.
        /// </summary>
        /// <param name="key">The key to check.</param>
        /// <returns>
        /// <c>true</c> if the key is pressed, otherwise <c>false</c>.
        /// </returns>
        public static bool IsKeyDown(KeyCode key)
        {
            return (GetKeyState((int)key) & KeyPressed) != 0;
        }
    
        /// <summary>
        /// Gets the key state of a key.
        /// </summary>
        /// <param name="key">Virtuak-key code for key.</param>
        /// <returns>The state of the key.</returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        private static extern short GetKeyState(int key);
    }
    
    0 讨论(0)
  • 2020-11-28 15:14
    var isUp = Console.ReadKey().Key == ConsoleKey.UpArrow;
    

    or another example, just for your case:

    while (true)
    {
       var ch = Console.ReadKey(false).Key;
       switch(ch)
       {
           case ConsoleKey.Escape:
              ShutdownRobot();
              return;
           case ConsoleKey.UpArrow:
              MoveRobotUp();
              break;
           case ConsoleKey.DownArrow:
              MoveRobotDown();
              break;
       }
    }
    
    0 讨论(0)
提交回复
热议问题