0

In a simple test program that i made, you can increment a value with Console.ReadKey(). However, you can hold the button, and it will just keep increasing the value. I want my program to wait for the key to be released, so you can't hold the key. How do i do this?

Quadro
  • 21
  • 4

3 Answers3

0

Try to use Control.keyPress() events instead of ReadKey().

Here are some examples and references

https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.control.keypress?view=netframework-4.7.2

0

I think you need to use a keyboard hook. Use a class, like has been described in https://social.msdn.microsoft.com/Forums/vstudio/en-US/88ae8842-5301-4b15-830e-1d6282303508/how-to-listen-to-keyboard-inputs?forum=netfxbcl

This class is a global keyboard hook handler. In the handler method 'OnHookCallback' do anything you want. It does like the ReadKey() method. You can read the pressed key, write the value of the key, or do anything you want. Also, you can detect that this key event is KeyDown or KeyUp. Therefore the puzzle is complete. You have the key value and you know the key down and key up events. So, you can compare the key value when is pressed down with the value when is released. If you had, for example, five-time rising of KeyDown event without any KeyUp event, it means, the key has been held and have been kept for a while. So, in this type of situations, you could avoid the increasing of the counter.

However, you use a console application, so you need to change the main method as is described in C# global keyboard hook, that opens a form from a console application

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);

    LowLevelKeyboardHook kbh = new LowLevelKeyboardHook();
    kbh.OnKeyPressed += kbh_OnKeyPressed;
    kbh.OnKeyUnpressed += kbh_OnKeyUnpressed;
    kbh.HookKeyboard();

    Application.Run();

    kbh.UnHookKeyboard();
}
0

You can use GetKeyState function here.

  1. Let's use modified code from this answer https://stackoverflow.com/a/9356006/4631959
    We will use ConsoleKey instead of Key as we don't use WinForms here.

    using System;
    using System.Runtime.InteropServices;
    
    namespace NetFramework
    {
        public static class Keyboard
        {
            [Flags]
            private enum KeyStates
            {
                None = 0,
                Down = 1,
                Toggled = 2
            }
    
    
        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern short GetKeyState(int keyCode);
    
        private static KeyStates GetKeyState(ConsoleKey key)
        {
            KeyStates state = KeyStates.None;
    
            short retVal = GetKeyState((int)key);
    
            //If the high-order bit is 1, the key is down
            //otherwise, it is up.
            if ((retVal & 0x8000) == 0x8000)
                state |= KeyStates.Down;
    
            //If the low-order bit is 1, the key is toggled.
            if ((retVal & 1) == 1)
                state |= KeyStates.Toggled;
    
            return state;
        }
    
        public static bool IsKeyDown(ConsoleKey key)
        {
            return KeyStates.Down == (GetKeyState(key) & KeyStates.Down);
        }
    
        public static bool IsKeyToggled(ConsoleKey key)
        {
            return KeyStates.Toggled == (GetKeyState(key) & KeyStates.Toggled);
        }
    }
    
    }
  2. Wrap Console.ReadKey() method.
    This method will return key only when you release the button.

    static ConsoleKey ReadKey()
    {
        var key = Console.ReadKey().Key;    
        //wait while key is pressed
        while (Keyboard.IsKeyDown(key))
        {
        }        
        //flush input stream
        while (Console.KeyAvailable)
            Console.ReadKey(true);        
        return key;
    }
  3. Test the method.

    static void Main(string[] args)
    {
        int i = 0;
        while (true)
        {
            var key = ReadKey();
            if (key == ConsoleKey.UpArrow)
            {
                Console.WriteLine(++i);
            }
        }
    }