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