1

I'm writing a console app in C#, which reads user input using Console.ReadKey(). It has code that's similar to this:

while(true)
{
    switch(Console.ReadKey(true).Key)
    {
        case ConsoleKey.Enter:
            //code
        case ConsoleKey.UpArrow:
            //code
        case ConsoleKey.DownArrow:
            //code
        case ConsoleKey.Escape:
            //code
    }
}

Now the problem is, if the user holds down any key for more than half a second, Windows registers it as multiple key presses. So if, for the example, the Enter key is held down for a second, the code that goes after case ConsoleKey.Enter: runs about ten times, and I don't want that.

How do I make it so that holding a button down registers as only one key press? Will I have to use Windows Forms for that? (currently my code only relies on the Console class).

gardenapple
  • 146
  • 1
  • 12
  • @HenkHolterman If someone intentionally spams the button, I'm okay with that. I just don't want code running multiple times if they hold down the button for too long by accident. – gardenapple Jul 16 '16 at 12:55

2 Answers2

1

If the goal is just to prevent entering keystrokes too fast, something like this might work:

        DateTime lastPressedTime = DateTime.MinValue;
        while (true)
        {
            var key = Console.ReadKey(true).Key;
            if (DateTime.Now > lastPressedTime.AddSeconds(.5))
            {
                switch (key)
                {
                    case ConsoleKey.Enter:
                    //code
                    case ConsoleKey.UpArrow:
                    //code
                    case ConsoleKey.DownArrow:
                    //code
                    case ConsoleKey.Escape:
                    //code
                }
            }
            lastPressedTime = DateTime.Now;
        }

However it will be annoying to the user if they are legitimately typing fast since it will discard anything that comes in quicker than 1/2 second from the last keypress.

If you really want to be sure they aren't just holding down the key too long, you need to monitor for a KeyUp event and only accept another keystroke after you have seen the KeyUp. It is easy using Winforms. It gets a bit more complicated with a Console application.

This question may give more ideas on what it would take to monitor for key state in a Console application: C# arrow key input for a console app

Community
  • 1
  • 1
Steve In CO
  • 5,746
  • 2
  • 21
  • 32
  • Actually I kinda like the first approach. It's not exactly what I was asking for, but after reducing the "key press cooldown" to 50 milliseconds I found that it works quite nicely for my program. – gardenapple Jul 16 '16 at 14:10
0

You can use the Timer class to read the key from the console only once per a period of time (say, 50 miliseconds or something). When a user press and holds a key it will still be readed several times but you can control how many times per second your code will be executed.

Ivan Yurchenko
  • 3,762
  • 1
  • 21
  • 35
  • I think the OP wants to run code only once no matter how much the user holded down the key before releasing it – niceman Jul 16 '16 at 13:03
  • @niceman That is correct. I just want to make it so that holding down the button registers as only one key press, I don't want to set a "speed limit" to key presses or anything. I should probably clarify that in my question. – gardenapple Jul 16 '16 at 13:10