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

发布于 2024-10-06 07:28:10 字数 1784 浏览 1 评论 0原文

我有一个用 C# 编写的简单控制台应用程序。我希望能够检测箭头键按下情况,这样我就可以允许用户进行转向。如何使用控制台应用程序检测 keydown/keyup 事件?

我所有的谷歌搜索都找到了有关 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 窗体。这很烦人,因为我无法在无头系统上使用它。要求 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 调用。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

霊感 2024-10-13 07:28:10

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

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

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);
}
静若繁花 2024-10-13 07:28:10
var isUp = Console.ReadKey().Key == ConsoleKey.UpArrow;

或另一个例子,仅适合您的情况:

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;
   }
}
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;
   }
}
梨涡 2024-10-13 07:28:10
System.Console.ReadKey(true).Key == ConsoleKey.UpArrow

你可以把它放到一个旋转中,比如:

while(Running)
{
  DoStuff();
  System.Console.ReadKey(true).Key == ConsoleKey.UpArrow
  Thread.Sleep(1)
}
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)
}
眉目亦如画i 2024-10-13 07:28:10

我有同样的问题,你和我在这里发现了一篇使用任务的有趣帖子。
原始帖子可以在这里找到:
C# 控制台应用程序 - 如何我总是从控制台读取输入?

我必须通过 Raspberry GPIO(使用单声道 C#)模拟 PWM 输出来测试 LCD 背光。我想用两个简单的键来更改占空比(上/下)和一个额外的键来停止程序。

我尝试了这个(变量):

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

主程序:

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;
        }
    }
}

当需要增加占空比时,按“W”键使主任务更改占空比变量(duty);与“S”键递减相同。当按下“X”键时程序结束。

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.

带上头具痛哭 2024-10-13 07:28:10

我已经晚了 10 年,但我想与将来可能会阅读此帖子的其他人分享这一点。

有一种更简单的方法可以实现 Ergwun 所说的。

您无需创建枚举和类,只需一行代码即可获得结果。

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern short GetAsyncKeyState(int key); 
   
. . .

bool[] keys = new bool[4];

for (int i = 0; i < 4; i++)                            
    keys[i] = (0x8000 & GetAsyncKeyState((char)"\x25\x26\x27\x28"[i])) != 0;

您需要从 User32.dll 导入 GetKeyState 或在我的例子中导入 GetAsyncKeyState 方法。

然后你只需要遍历一个循环并检查是否按下了任何键。
字符串中的这些奇怪的数字是 虚拟键代码 分别代表左、上、右、下箭头键。

布尔结果存储在一个数组中,稍后可以循环查看是否按下了某个键。您只需为程序定义数组中键的顺序

I am 10 years too late, but I wanted to share this with others that might read this thread in the future.

There is a simpler way to achieve what Ergwun said.

Instead of creating the the Enum and Class you can achieve the result in one line of code.

[System.Runtime.InteropServices.DllImport("user32.dll")]
static extern short GetAsyncKeyState(int key); 
   
. . .

bool[] keys = new bool[4];

for (int i = 0; i < 4; i++)                            
    keys[i] = (0x8000 & GetAsyncKeyState((char)"\x25\x26\x27\x28"[i])) != 0;

You need to import the GetKeyState or in my case GetAsyncKeyState method from User32.dll.

Then you just need to go through a loop and check if any of the keys were pressed.
These strange numbers in the string are the Virtual-Key Codes for the left, up, right and down arrow keys respectively.

The boolean result is stored inside an array that can be looped through later to see if some key was pressed. You just need to define the order of the keys in the array for your program

柠檬色的秋千 2024-10-13 07:28:10

让我们看一下 .NET System.Console 类并复制什么
它在内部执行,请查看它的源代码

:需要创建一个线程来持续池化来自 Kernel32.dllReadConsoleInput Win32 Api 的 Key 事件。该 API 还返回鼠标/焦点事件,因此并非所有事件都适合您的用例。该 API 会阻塞当前线程,直到有新事件到达。您必须阅读ReadConsoleInput 参考文档来改进以下代码。

此应用程序无法在新的 Windows 终端中运行,因为 WT 只发送 KeyUp 事件(抱歉,过于简单化,不准确!它发送 VT 序列,据我所知,它们不单独处理按键按下/按下)。因此,请在常规控制台主机窗口中使用它。

以下只是一个工作示例。需要工作。

using System.Runtime.InteropServices;
using static Win32Native;

class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello");
        while (true)
        {
            var key = KeyHandler.ReadKey();
            Console.WriteLine($"Event:{key.KeyPressType} Key:{key.Key.Key}");
        }
    }
}

enum KeyPressType { KeyUp, KeyDown, Unknown }
class SimpleKeyRecord { public KeyPressType KeyPressType; public ConsoleKeyInfo Key; }
class KeyHandler
{
    static IntPtr _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE);
    
    public static SimpleKeyRecord ReadKey()
    {
        var result = new SimpleKeyRecord();
        Win32Native.InputRecord ir;
        int numEventsRead;

        if (!Win32Native.ReadConsoleInput(_consoleInputHandle, out ir, 1, out numEventsRead) || numEventsRead == 0)
        {
            throw new InvalidOperationException();
        }

        if (ir.eventType != 1)  // see https://learn.microsoft.com/en-us/windows/console/input-record-str
        {
            result.KeyPressType = KeyPressType.Unknown; // Focus/Mouse/Menu event.
            return result;
        }

        result.KeyPressType = ir.keyEvent.keyDown ? KeyPressType.KeyDown : KeyPressType.KeyUp;

        ControlKeyState state = (ControlKeyState)ir.keyEvent.controlKeyState;
        bool shift = (state & ControlKeyState.ShiftPressed) != 0;
        bool alt = (state & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0;
        bool control = (state & (ControlKeyState.LeftCtrlPressed | ControlKeyState.RightCtrlPressed)) != 0;

        result.Key = new ConsoleKeyInfo((char)ir.keyEvent.uChar, (ConsoleKey)ir.keyEvent.virtualKeyCode, shift, alt, control);

        short virtualKeyCode = ir.keyEvent.virtualKeyCode;

        return result;
    }
}

class Win32Native
{
    public const int STD_INPUT_HANDLE = -10;

    [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr GetStdHandle(int whichHandle);
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct InputRecord
    {
        internal short eventType;
        internal KeyEventRecord keyEvent;
    }

    // Win32's KEY_EVENT_RECORD
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct KeyEventRecord
    {
        internal bool keyDown;
        internal short repeatCount;
        internal short virtualKeyCode;
        internal short virtualScanCode;
        internal char uChar; // Union between WCHAR and ASCII char
        internal int controlKeyState;
    }

    [Flags]
    internal enum ControlKeyState
    {
        RightAltPressed = 0x0001,
        LeftAltPressed = 0x0002,
        RightCtrlPressed = 0x0004,
        LeftCtrlPressed = 0x0008,
        ShiftPressed = 0x0010,
        NumLockOn = 0x0020,
        ScrollLockOn = 0x0040,
        CapsLockOn = 0x0080,
        EnhancedKey = 0x0100
    }
}

它同时检测多个按键。
工作示例

Let's take a look at .NET System.Console class and replicate what
it does internally, see it's source code:

You need to create a thread that constantly pools Key events from ReadConsoleInput Win32 Api from Kernel32.dll. The api also returns mouse/focus events, so not all events will be of interest for your use case. The api blocks the current thread until a new event arrives. You must read ReadConsoleInput reference docs to improve the following code.

This apps doesn't work within the new Windows Terminal, because WT only sends KeyUp events (inaccurate oversimplification, sorry! It sends VT sequences as AFAIK they dont handle key down/up separtedly). So use it in a regular Console Host window.

The following is just a working sample. Needs work.

using System.Runtime.InteropServices;
using static Win32Native;

class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello");
        while (true)
        {
            var key = KeyHandler.ReadKey();
            Console.WriteLine(
quot;Event:{key.KeyPressType} Key:{key.Key.Key}");
        }
    }
}

enum KeyPressType { KeyUp, KeyDown, Unknown }
class SimpleKeyRecord { public KeyPressType KeyPressType; public ConsoleKeyInfo Key; }
class KeyHandler
{
    static IntPtr _consoleInputHandle = Win32Native.GetStdHandle(Win32Native.STD_INPUT_HANDLE);
    
    public static SimpleKeyRecord ReadKey()
    {
        var result = new SimpleKeyRecord();
        Win32Native.InputRecord ir;
        int numEventsRead;

        if (!Win32Native.ReadConsoleInput(_consoleInputHandle, out ir, 1, out numEventsRead) || numEventsRead == 0)
        {
            throw new InvalidOperationException();
        }

        if (ir.eventType != 1)  // see https://learn.microsoft.com/en-us/windows/console/input-record-str
        {
            result.KeyPressType = KeyPressType.Unknown; // Focus/Mouse/Menu event.
            return result;
        }

        result.KeyPressType = ir.keyEvent.keyDown ? KeyPressType.KeyDown : KeyPressType.KeyUp;

        ControlKeyState state = (ControlKeyState)ir.keyEvent.controlKeyState;
        bool shift = (state & ControlKeyState.ShiftPressed) != 0;
        bool alt = (state & (ControlKeyState.LeftAltPressed | ControlKeyState.RightAltPressed)) != 0;
        bool control = (state & (ControlKeyState.LeftCtrlPressed | ControlKeyState.RightCtrlPressed)) != 0;

        result.Key = new ConsoleKeyInfo((char)ir.keyEvent.uChar, (ConsoleKey)ir.keyEvent.virtualKeyCode, shift, alt, control);

        short virtualKeyCode = ir.keyEvent.virtualKeyCode;

        return result;
    }
}

class Win32Native
{
    public const int STD_INPUT_HANDLE = -10;

    [DllImport("kernel32.dll", CharSet = System.Runtime.InteropServices.CharSet.Ansi, SetLastError = true)]
    public static extern IntPtr GetStdHandle(int whichHandle);
    
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    internal static extern bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead);

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct InputRecord
    {
        internal short eventType;
        internal KeyEventRecord keyEvent;
    }

    // Win32's KEY_EVENT_RECORD
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    internal struct KeyEventRecord
    {
        internal bool keyDown;
        internal short repeatCount;
        internal short virtualKeyCode;
        internal short virtualScanCode;
        internal char uChar; // Union between WCHAR and ASCII char
        internal int controlKeyState;
    }

    [Flags]
    internal enum ControlKeyState
    {
        RightAltPressed = 0x0001,
        LeftAltPressed = 0x0002,
        RightCtrlPressed = 0x0004,
        LeftCtrlPressed = 0x0008,
        ShiftPressed = 0x0010,
        NumLockOn = 0x0020,
        ScrollLockOn = 0x0040,
        CapsLockOn = 0x0080,
        EnhancedKey = 0x0100
    }
}

It detects multiple keydowns simultaneously.
working sample

柏林苍穹下 2024-10-13 07:28:10

你可以这样做

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
}

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
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文