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 console app?
All my googling has led to info about windows Forms. I don't have a GUI. This is a console app (to control a robot over a serial port).
I have functions written to handle these events, but I have no idea how to register to actually receive the events:
  private void myKeyDown(object sender, KeyEventArgs e)
  {
      switch (e.KeyCode)
      {
          case Keys.Left:
                 ...
          case Keys.Right:
                 ...
          case Keys.Up:
                 ...
      }
  }
  private void myKeyUp(object sender, KeyEventArgs e)
  {
      ... pretty much the same as myKeyDown
  }
This is probably a really basic question, but I'm fairly new to C#, and I've never needed to get this kind of input before.
Update:  Many are suggesting I use System.Console.ReadKey(true).Key.  This will not help.  I need to know the moment a key is held down, when it is released, with support for multiple keys to be held down simultaneously.  Also, ReadKey is a blocking call -- which means that the program will stop and wait for a key to be pressed.
Update: It seems that the only viable way to do this is to use Windows Forms. This is annoying, as I cannot use it on a headless system. Requiring a Form GUI to receive keyboard input is ... stupid.
But anyway, for posterity, here's my solution. I created a new Form project in my .sln:
    private void Form1_Load(object sender, EventArgs e)
    {
        try
        {
            this.KeyDown += new KeyEventHandler(Form1_KeyDown);
            this.KeyUp += new KeyEventHandler(Form1_KeyUp);
        }
        catch (Exception exc)
        {
            ...
        }
    }
    void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        switch (e.KeyCode)
        {
            // handle up/down/left/right
            case Keys.Up:
            case Keys.Left:
            case Keys.Right:
            case Keys.Down:
            default: return;  // ignore other keys
        }
    }
    private void Form1_KeyUp(object sender, KeyEventArgs e)
    {
        // undo what was done by KeyDown
    }
Note that if you hold down a key, KeyDown will be called numerous times, and KeyUp will only be called once (when you release it). So you need to handle repeated KeyDown calls gracefully.
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;
   }
}
                        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);
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With