控制台应用程序的 C# 箭头键输入

标签 c# console-application user-input

我有一个用 C# 编写的简单控制台应用程序。我希望能够检测到箭头键的按下,这样我就可以让用户进行驾驶。如何使用控制台应用检测按键/按键事件?

我所有的谷歌搜索都导致了有关 Windows 窗体的信息。我没有图形用户界面。这是一个控制台应用程序(用于通过串行端口控制机器人)。

我编写了处理这些事件的函数,但我不知道如何注册才能实际接收这些事件:

  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
  }

这可能是一个非常基本的问题,但我是 C# 的新手,而且我以前从未需要获得这种输入。

更新:许多人建议我使用 System.Console.ReadKey(true).Key。这无济于事。我需要知道按下某个键的那一刻,何时释放它,并支持同时按下多个键。此外,ReadKey 是一个阻塞调用——这意味着程序将停止并等待按下某个键。

更新:似乎唯一可行的方法是使用 Windows 窗体。这很烦人,因为我不能在 headless 系统上使用它。要求 Form GUI 来接收键盘输入是……愚蠢的。

但无论如何,为了后代,这是我的解决方案。我在我的 .sln 中创建了一个新的 Form 项目:

    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
    }

请注意,如果您按住一个键,KeyDown 将被调用多次,而 KeyUp 只会被调用一次(当您松开它时)。因此,您需要优雅地处理重复的 KeyDown 调用。

最佳答案

现在有点晚了,但这里是如何在控制台应用程序中访问键盘状态。

请注意,它不是所有托管代码,因为它需要 GetKeyState从 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);
}

关于控制台应用程序的 C# 箭头键输入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36859023/

相关文章:

c# - DLL 引用有多昂贵?

c# - 写入现有分配控制台的新 cmd 进程

Javascript - 用户通过 HTML 输入标签输入来设置 Javascript 变量?

unity3d - 使用新输入系统损坏的按钮

.net - 如何使用 IHostedService 访问控制台应用程序中的命令行参数?

C - 读取用户输入

c# - 如何在 Windows 10 C# 中更新 sqlite.net pcl 中的行?

c# - 如何使用 Moles 作为构造函数?

c# - Parser.Default.ParseArguments 始终返回 false

c++ - 我应该使用成员变量还是在函数内部声明变量?