在CONSOLE C#中检测SINGLE键按下

时间:2017-07-29 19:16:50

标签: c# keypress

我是编码的新手,并决定从C#开始。我决定编写一个简单的控制台程序来检测按键,如果只按下Enter,它将显示数字。问题是你只需按住键即可继续显示数字。我应该将什么添加到我的代码中,以便程序只检测 SINGLE 按下并忽略用户 HOLDING 密钥? (我没有找到关于 CONSOLE C#此问题的任何内容,仅针对表单一。在此论坛上或在Web上都没有。

提前致谢

static void Main(string[] args)
{
    Console.WriteLine("Press Enter to play!");

    int num = 0;
    void WaitForKey(ConsoleKey key)
    {
        while (Console.ReadKey(true).Key != key)
        { }
    }

    for (int i = 0; i < 10; i++)
    {
        WaitForKey(ConsoleKey.Enter);
        Console.Write("{0} ", num);
        num++;
    }
}

4 个答案:

答案 0 :(得分:1)

如果您的任务是计算键入/持有键的更改量,您只需记住最后一个键即可完成

var lastChar = char.MaxValue;
var index = 0;
do
{
    var x = Console.ReadKey();
    if (lastChar != x.KeyChar)
    {
        lastChar = x.KeyChar;
        Console.WriteLine(++index);
    }
} while (index < 10);

如果你需要定义单个密钥,你可以使用StopWatch类检查从之前的密钥到来的时间(在示例300中仅用于测试,我建议深入研究它是否适合你的目标)

var sw = Stopwatch.StartNew();
do
{
    var x = Console.ReadKey();
    if (sw.ElapsedMilliseconds > 300)
    {
        Console.WriteLine(++index);
    }
    sw.Restart();
} while (index < 10);

或两种方式结合

答案 1 :(得分:0)

您是否尝试在num ++之后的循环中添加方法keyRelease:  WaitForKeyRelease(ConsoleKey.Enter);

在你的方法中:while(Console.ReadKey(true).Key == key)

你等到按下的键没有进入所以它就像一个键释放。

答案 2 :(得分:0)

您可以通过执行以下操作来检查是否输入了“输入”:

`

string input = Console.ReadLine();
if (input == "") {
     //do stuff
}

`

答案 3 :(得分:0)

是的,你不能在这里使用ReadKey。我建议使用ReadConsoleInput WinApi函数。您可以为此目的编写包装类,例如:

internal class KeyboardInput
{
    private readonly short _exitKey;
    private readonly uint[] _keyStates = new uint[short.MaxValue]; 

    public KeyboardInput(ConsoleKey exitKey)
    {
        _exitKey = (short) exitKey;

        // subscribe with empty delegates to prevent null reference check before call
        OnKeyDown += delegate { };
        OnKeyUp += delegate { };
    }

    public event Action<char, short> OnKeyDown;
    public event Action<char, short> OnKeyUp;

    public void Run()
    {
        var exitKeyPressed = false;
        var nRead = 0;
        var records = new INPUT_RECORD[10];

        var handle = GetStdHandle(STD_INPUT_HANDLE);
        while (!exitKeyPressed)
        {
            ReadConsoleInputW(handle, records, records.Length, ref nRead);

            for (var i = 0; i < nRead; i++)
            {
                // process only Key events
                if (records[i].EventType != KEY_EVENT) continue;

                // process key state
                ProcessKey(records[i].KeyEvent.wVirtualKeyCode, records[i].KeyEvent.bKeyDown,
                    records[i].KeyEvent.UnicodeChar);

                // check for exit key press
                if ((exitKeyPressed = records[i].KeyEvent.wVirtualKeyCode == _exitKey) == true) break;
            }
        }
    }

    private void ProcessKey(short virtualKeyCode, uint keyState, char key)
    {
        if (_keyStates[virtualKeyCode] != keyState)
            if (keyState == 1) OnKeyDown(key, virtualKeyCode);
            else OnKeyUp(key, virtualKeyCode);

        _keyStates[virtualKeyCode] = keyState;
    }

    #region Native methods

    private const short KEY_EVENT = 0x0001;
    private const int STD_INPUT_HANDLE = -10;

    [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern IntPtr GetStdHandle(int nStdHandle);

    [DllImport("Kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern bool ReadConsoleInputW(IntPtr hConsoleInput, [Out] INPUT_RECORD[] lpBuffer, int nLength,
        ref int lpNumberOfEventsRead);

    [StructLayout(LayoutKind.Explicit)]
    private struct INPUT_RECORD
    {
        [FieldOffset(0)] public readonly short EventType;

        //union {
        [FieldOffset(4)] public KEY_EVENT_RECORD KeyEvent;

        //[FieldOffset(4)]
        //public MOUSE_EVENT_RECORD MouseEvent;
        //[FieldOffset(4)]
        //public WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
        //[FieldOffset(4)]
        //public MENU_EVENT_RECORD MenuEvent;
        //[FieldOffset(4)]
        //public FOCUS_EVENT_RECORD FocusEvent;
    }

    [StructLayout(LayoutKind.Sequential)]
    private struct KEY_EVENT_RECORD
    {
        public readonly uint bKeyDown;
        public readonly short wRepeatCount;
        public readonly short wVirtualKeyCode;
        public readonly short wVirtualScanCode;
        public readonly char UnicodeChar;
        public readonly int dwControlKeyState;
    }

    #endregion
}

使用示例:

internal class Program
{
    private static void Main(string[] args)
    {
        var kbInput = new KeyboardInput(ConsoleKey.Escape);
        kbInput.OnKeyDown += OnKeyDown;
        kbInput.OnKeyUp += OnKeyUp;

        kbInput.Run();
    }

    private static void OnKeyDown(char key, short code)
    {
        Console.WriteLine($"Key pressed: {key} (virtual code: 0x{code:X})");
    }

    private static void OnKeyUp(char key, short code)
    {
        Console.WriteLine($"Key released: {key} (virtual code: 0x{code:X})");
    }
}