I'm porting a small C++ console game to C# and it seems that I can't stop key presses from being printed to the console.
In C++ I get the keystroke with this method, which also suppress the keystrokes from being printed to the console:
bool Game::getInput(char *c)
{
if (_kbhit())
{
*c = _getch();
return true;
}
return false;
}
I tried to do the equivalent in C# by doing:
Key = Console.ReadKey();
But this does not suppress the character from being printed to the console, causing obvious problems. Any ideas on how to remedy this?
You want Console.ReadKey(true)
Obtains the next character or function key pressed by the user. The pressed key is optionally displayed in the console window.
The argument - which is called intercept:
Determines whether to display the pressed key in the console window. true to not display the pressed key; otherwise, false.
The ReadKey method has an overload that takes a bool as a parameter. Pass in true and it will not display the input in the console.
Related
I am currently working on a little lottery console game and wanted to add a "Working" mechanic. I created a new method and want to add multiple tasks where you have to press a specific key like the space bar for example multiple times. So something like this (but actually working):
static void Work()
{
Console.WriteLine("Task 1 - Send analysis to boss");
Console.WriteLine("Press the spacebar 3 times");
Console.ReadKey(spacebar);
Console.ReadKey(spacebar);
Console.ReadKey(spacebar);
Console.WriteLine("Task finished - Good job!");
Console.ReadKey();
}
The Console.ReadKey() method returns a ConsoleKeyInfo structure which gives you all the information you need on which key and modifiers were pressed. You can use this data to filter the input:
void WaitForKey(ConsoleKey key, ConsoleModifiers modifiers = default)
{
while (true)
{
// Get a keypress, do not echo to console
var keyInfo = Console.ReadKey(true);
if (keyInfo.Key == key && keyInfo.Modifiers == modifiers)
return;
}
}
In your use case you'd call that like this:
WaitForKey(ConsoleKey.SpaceBar);
Or you could add a WaitForSpace method that specifically checks for ConsoleKey.SpaceBar with no modifiers.
For more complex keyboard interactions like menus and general input processing you'll want something a bit more capable, but the basic concept is the same: use Console.ReadKey(true) to get input (without displaying the pressed key), check the resultant ConsoleKeyInfo record to determine what was pressed, etc. But for the simple case of waiting for a specific key to be pressed that will do the trick.
I would like to check if the user will make a kepress again after the first one to implement a pause function in a while cycle. The console window is not on focus so I can't use Console.Read()
while (true)
{
if (GetAsyncKeyState(0x21) != 0)
break; //work just fine, if ESC press it exit while
if (GetAsyncKeyState(0x05) != 0)
{
sw.Start();
while (sw.ElapsedMilliseconds < 2000)
{
// if side mouse button is press, it wait 2sec, work just fine
}
sw.Reset();
}
if (GetAsyncKeyState(0x42) != 0)
{
while (GetAsyncKeyState(0x42) == 0)
{
// wait the second B pressing to resume but it dosen't work
}
}
main_function();
}
This code seems to not work, I check GetAsyncKeyState with writeline and it seems that it get the keypressed state for few ms so the pause cicle will end.
I seems that in console c# I can't use ad hoc functions that c# have for forms to check it.
Thanks!
The solution is:
// if pressed the first time
if (GetAsyncKeyState('B'))
{
//if previously detected and still held down
while (!((GetAsyncKeyState('B')) & 0b1000'0000'0001))
{
//wait in here
}
//if key not pressed
while (!GetAsyncKeyState('B'))
{
//wait in here
}
//if you get here, B was pressed, released and pressed again
}
I don't recommend using GetASyncKeyState for anything but quick and simple Proof of Concepts due to the remarks you will read below.
From MSDN:
Return value
Type: SHORT
If the function succeeds, the return value specifies whether the key was pressed since the last call to GetAsyncKeyState, and whether the key is currently up or down. If the most significant bit is set, the key is down, and if the least significant bit is set, the key was pressed after the previous call to GetAsyncKeyState.
Important remarks:
Although the least significant bit of the return value indicates whether the key has been pressed since the last query, due to the pre-emptive multitasking nature of Windows, another application can call GetAsyncKeyState and receive the "recently pressed" bit instead of your application. The behavior of the least significant bit of the return value is retained strictly for compatibility with 16-bit Windows applications (which are non-preemptive) and should not be relied upon.
i'm attempting my first c# console-based game. I created a centered credits intro with a "press any key to continue..." printed at the end. I used Console.ReadKey() to emulate a pause as it waits for user input. The problem is that you can 'stack' inputs, there is probably a better term but essentially, while the console is in a timeout the key inputs are still read and are queued until the timeout ends.
for example;
//10 second wait
//this is where I would press a key
Thread.Sleep(10000);
char x = Console.ReadKey().KeyChar;
//x will be equal to whatever key I pressed before the timeout
this is not the functionality i'm after. does anyone have a solution to this e.g; not use Thread.Sleep() or Console.ReadKey()
If you still do not understand the question, press a key while the Thread.Sleep() is still in effect and the readkey, after the time is up will print that character. does anyone know how to stop the reading of the key?
If you would like actual project code, just ask. Although I see it as irrelevant for this question.
If you want to clear the buffer before waiting for a key, you can call Console.ReadKey(true) in a loop for as long as there is a KeyAvailable. Passing true to the method specifies that the key should be intercepted and not be output to the console window.
For example:
Thread.Sleep(TimeSpan.FromSeconds(10));
// Clear buffer by "throwing away" any keys that were pressed while we were sleeping
while(Console.KeyAvailable) Console.ReadKey(true);
char x = Console.ReadKey().KeyChar;
I'm trying to make a console application in C#. When using Console.ReadKey and typing Ctrl + S the application seems to be "waiting" on another keypress because the next key I type also gets eaten.
How can I prevent this from happening?
After some digging the only way I could figure out how to do this is to call some native methods to disable ENABLE_LINE_INPUT. I don't know why this works because the docs for ENABLE_LINE_INPUT say:
The ReadFile or ReadConsole function returns only when a carriage return character is read. If this mode is disabled, the functions return when one or more characters are available.
Which doesn't really seem related. Especially since ReadKey doesn't wait for return anyways.
Maybe someone else can explain it better?
Code:
int mode = 0;
GetConsoleMode(handle, ref mode);
mode &= ~0x0002; // Disable ENABLE_LINE_INPUT. Lets ctrl-s work for some reason.
SetConsoleMode(handle, mode);
I am not using windows forms so this is not a duplicate of Capture keystroke without focus in console. Please remove the duplicate label or direct me somewhere else
So have been away from C# for a long time and trying to get back into it. I am messing with a small console app that requires inputting text from the user. The whole program works fine but now I want to add a check to see if escape is ever pressed.
I originally used ReadKey, but that just checks the current key which has two problems.
1. it uses the key pressed, so strings are missing a character (the one which was checked)
2. it is only in the moment. I want it to be passively waiting until its pressed
What would be the best way to do this?
ex:
I type the string "Hello World!"
If I press the desired key(lets say escape) at any time, I want it to react. Otherwise the string should be entered like normal
edit
example of made up dictionary program (yes, I know there is already a class for this)
while (Console.ReadKey().Key != ConsoleKey.Escape)
{
string entry = Console.ReadLine();
if (!entry.Contains(","))
{
...
}
else
{
...
}
}
Thank you all very much for your time.
Not sure what you're getting at but you can use this to detect if the Escape key was pressed.
if (Console.KeyAvailable)
if (Console.ReadKey(true).Key == ConsoleKey.Escape)
{
// Do something
}
}
Or alternatively use a loop that breaks when Escape is entered:
var x = Console.ReadKey();
while (x.Key.ToString() != "Escape")
x = Console.ReadKey();