C# 在控制台C中检测单键按下#

C# 在控制台C中检测单键按下#,c#,keypress,C#,Keypress,我不熟悉编码,决定从C开始。我决定写一个简单的控制台程序来检测按键,如果只按Enter键,它就会显示数字。问题是,只要按住键,它就会继续显示数字。我应该在我的代码中添加什么,这样程序只会检测到一次按下,而忽略用户是否在按住键? (我在控制台C#上找不到关于这个问题的任何信息,只在Forms one上找到。既不在这个论坛上,也不在Web上) 提前谢谢 static void Main(string[] args) { Console.WriteLine("Press Enter to pl

我不熟悉编码,决定从C开始。我决定写一个简单的控制台程序来检测按键,如果只按Enter键,它就会显示数字。问题是,只要按住键,它就会继续显示数字。我应该在我的代码中添加什么,这样程序只会检测到一次按下,而忽略用户是否在按住键? (我在控制台
C#
上找不到关于这个问题的任何信息,只在Forms one上找到。既不在这个论坛上,也不在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++;
    }
}
static void Main(字符串[]args)
{
控制台。WriteLine(“按回车键播放!”);
int num=0;
void WaitForKey(控制台键)
{
while(Console.ReadKey(true).Key!=Key)
{ }
}
对于(int i=0;i<10;i++)
{
WaitForKey(ConsoleKey.Enter);
Write(“{0}”,num);
num++;
}
}

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

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

您可以等待,直到按下的键没有进入,这就像一个按键释放。

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

`


`

如果您的任务是计算键入/保留键的更改量,则只需记住最后一个键即可

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

或者将这两种方法结合使用

是的,您不能在此处使用
ReadKey
。我建议使用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
}
你不能在另一个方法(Main)中声明一个方法(WaitForKey)@L.B实际上,C#7.0引入了本地函数@L.B,它可以工作(没有显示任何错误),对我来说也可以工作)它的可能重复不是问题,这是一个特性。您的程序运行速度已经慢了数百万倍,增加一个数字需要几分之一纳秒。但在人眼看来,键盘重复的速度足够快,看起来很快。即使需要100毫秒,eon也会占用处理器周期。您必须重新思考这一点,我们无法从片段中看出您打算实现什么。不要使用Thread.Sleep()使其更慢。
var sw = Stopwatch.StartNew();
do
{
    var x = Console.ReadKey();
    if (sw.ElapsedMilliseconds > 300)
    {
        Console.WriteLine(++index);
    }
    sw.Restart();
} while (index < 10);
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})");
    }
}