I'm writing a small application which will wait for a key press, then perform an action based on what key is pressed. For example, if no key is pressed, it will just continue waiting, if key 1 is pressed, it will perform action 1, or if key 2 is pressed it will perform action 2. I have found several helpful posts so far, this one being an example. From this, I have the following code so far.
do
{
while (!Console.KeyAvailable)
{
if (Console.ReadKey(true).Key == ConsoleKey.NumPad1)
{
Console.WriteLine(ConsoleKey.NumPad1.ToString());
}
if (Console.ReadKey(true).Key == ConsoleKey.NumPad2)
{
Console.WriteLine(ConsoleKey.NumPad1.ToString());
}
}
} while (Console.ReadKey(true).Key != ConsoleKey.Escape);
There's a couple of issue with this, which you may have guessed already.
1)
Using the ReadKey to detect which key is pressed results in a temporary pause, meaning the key will have to be pressed. I really need to find a way to avoid this. Possibly using KeyAvailable, but I'm not sure how you can use this to detect which key has been pressed - any ideas?
2)
For some reason, the Escape key does not escape out of the application. It does if I remove the if statements, however running the code as is above does not let me exit the application using the designated key - any ideas?
The reason for the behavior is simple:
You get inside the nested loop as long as there is no key pressed.
Inside you are waiting for a key and read it - So again no key is available.
even if you press escape, you are still inside the nested loop and never get out of it.
What you should of done is loop until you have a key available, then read it and check its value:
ConsoleKey key;
do
{
while (!Console.KeyAvailable)
{
// Do something, but don't read key here
}
// Key is available - read it
key = Console.ReadKey(true).Key;
if (key == ConsoleKey.NumPad1)
{
Console.WriteLine(ConsoleKey.NumPad1.ToString());
}
else if (key == ConsoleKey.NumPad2)
{
Console.WriteLine(ConsoleKey.NumPad1.ToString());
}
} while (key != ConsoleKey.Escape);
Related
I would like to make a program which will let the user decide what program to run, by pressing certain keys. I have now come so far that some of these keys work perfectly. However I have now come to a problem that I have a difficult time to solve. Now when I press a key it activates the same thing that was activated before even though I press a different key. I believe that the issue lies in the WaitForKey()-method, but I am not sure where in there. Can you help me to locate the issue and bring in some solutions to this?
note: hasBeenPressed is a Boolean value which tells if the key has already been pressed or not and if so it should avoid activating some other functionality automatically.
public static void WaitForKey(ConsoleKey key) {
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
if (keyInfo.Key == key && hasBeenPressed == false) {
hasBeenPressed = true;
return;
}
else if (keyInfo.Key == key) {
hasBeenPressed = false;
return;
}
}
I use the WaitForKey() in this context:
for (int i = 0; i < mySignalChain.Count - 1; i++) {
if (keyPress.Key == ConsoleKey.I) {
pedalsActivated(mySignalChain)
WaitForKey(ConsoleKey.I);
}
I hope this was clear otherwise I will try to elaborate on this.
Thanks in advance!
Based on the description of what you would like to achieve,
I would like to make a program which will let the user decide what program to run, by pressing certain keys.
I wrote the following Console Application that will execute a different function depending on the key you press (I, J, or K), and will keep asking for keys until the user presses a different key, in which case the program will finish.
var exit = false;
ConsoleKeyInfo keyInfo;
do
{
Console.WriteLine("Please enter a new Key");
keyInfo = Console.ReadKey();
Console.WriteLine();
switch (keyInfo.Key)
{
case ConsoleKey.I:
FunctionFor_I();
break;
case ConsoleKey.J:
FunctionFor_J();
break;
case ConsoleKey.K:
FunctionFor_K();
break;
default:
ExitProgram();
break;
}
}
while (exit == false);
void FunctionFor_I()
{
Console.WriteLine("I has been pressed");
}
void FunctionFor_J()
{
Console.WriteLine("J has been pressed");
}
void FunctionFor_K()
{
Console.WriteLine("K has been pressed");
}
void ExitProgram()
{
exit = true;
}
I tried to replicate your code first and see how it works, but I couldn't understand its purpose so I focused on your textual description of the problem. If this is not what you intended, please post the full version of your code and I'll try to reproduce it.
I have now fixed my issue (somewhat) by doing the following:
ConsoleKeyInfo keyPress = Console.ReadKey(true);
while (keyPress.Key != ConsoleKey.Q) {
switch (keyPress.Key) {
case ConsoleKey.I:
pedalsActivated(mySignalChain);
Console.WriteLine("");
WaitForKey(ConsoleKey.I);
keyPress = Console.ReadKey(true);
break;
.
.
.
}
By using my function WaitForKey() defined above I can now activate my functions while at the same time avoiding a certain key being spammed. But then I also reset the keyPress (by: keyPress = Console.Readkey(true);) so that other functions can be called with other keys - though I have to press every key twice now to do so. This works better than having to press the keys far more than twice - however it would be optimal if I would only need to press each key once. And if anyone has an idea how to do so it would be much appreciated.
I have pause functionality in my application that I would like to interact with via keypresses in the System.Console window, and so the aptly-named ConsoleKey.Pause seems correct to use since the documentation says it corresponds to "the PAUSE key."
But whenever I press the key explicitly labeled Pause on my keyboard, Console.ReadKey never does anything:
while (_isOpen)
if (Console.ReadKey(false).Key == ConsoleKey.Pause)
_engine.TogglePause();
So what does ConsoleKey.Pause represent, and how might I trigger it? Or should I just invent my own shortcuts?
try below code:
while (_isOpen)
{
//Do you works need
if (Console.KeyAvailable)
{
var consoleKey = Console.ReadKey(true); //if true then keeps the key from
//the console
if (consoleKey.Key == ConsoleKey.Pause)
{
_engine.TogglePause();
}
}
}
I am creating a console application that shows simple animations with text. I have a thread that waits for the user to press "Up Arrow", "Down Arrow" and "Enter/Carriage Return/Return". It seems that the user must press any of these keys multiple times for the key to be registered, however sometimes the key is registered instantly. I assume, as you would too; that this is a problem with my code. I had a power failure last week and it wiped out part of my project, whilst rewriting my code this problem appeared.
I have tried using
if(Console.KeyAvailable == true && Console.Readkey().key == [one of the three keys])
to no avail.
I tried removing (Memory memory) from the class leaving it just
private static void GetKeyboardInput() {}
but this didn't seem to have any effect. BTW, when I did that the thread was declared like this
Thread getkey = new Thread(GetKeyboardInput);
perhaps I am doing this part wrong?
Here is some of my code neutered for size...
// declare listener thread and start it.
Thread GetKey = new Thread(() => GetKeyboardInput(memory));
GetKey.Start();
while (GetKey.ThreadState == ThreadState.Running)
{ Animate(memory); } // this is the text animation, ---> Menuitem <---
// the arrows move in and out from the menu item
Animate(memory); runs in the current tread, so it isn't the culprit, correct?
// This is the code that the thread runs
// Memory class contains all stored values for this program
private static void GetKeyboardInput(Memory memory)
{
while (Console.ReadKey().Key != ConsoleKey.Enter)
{
if (Console.ReadKey().Key == ConsoleKey.UpArrow)
{
// move up. There is more code here but not relevant
}
if (Console.ReadKey().Key == ConsoleKey.DownArrow)
{
// Move Down. Same as before
}
}
Thread.CurrentThread.Abort();
}
I expect that in less than 1000ms after a key is pressed that the revelant code within the if statements gets executed and the screen will show a change to the user, if any.
Actual results are that sometimes the program reacts to user input instanly, and other times the user has to press the key multiple times to register a change. This is not session dependent either, at any time during execution both of these above problems will/can be present.
The problem is that you're calling Console.ReadKey() multiple times: once to check that it's not enter, again to check whether it's UpArrow, yet again to check whether it was DownArrow. You probably want to read it once, and store it in a variable.
// This is the code that the thread runs
// Memory class contains all stored values for this program
private static void GetKeyboardInput(Memory memory)
{
while (true)
{
var key = Console.ReadKey().Key;
if (key == ConsoleKey.Enter)
{
break;
}
else if (key == ConsoleKey.UpArrow)
{
// move up. There is more code here but not relevant
// meaning these values effect the animation and nothing else
}
else if (key == ConsoleKey.DownArrow)
{
// Move Down. Same as before
}
}
// No need to call Thread.Abort - exiting this method does the same
}
I need to make it to where my code will only exit the loop when the key that is pressed, is released. I am doing this is console and will need to stay in console.
Here is an example of the code.
ConsoleKeyInfo = ki;
while (true)
{
ki = Console.ReadKey();
if (ki.Key == ConsoleKey.A)
{
Console.Write("A");
}
}
As you can see above, when the A key is pressed, it will write A in the console. If you hold down the A key, it will continuously write A.
What I'm wanting is for the console to write A ONCE until the A key is released. Then, if you press A again, it will print again.
I've thought about using "KeyUp" but I'm not able to use it on a console application. But something that would accomplish the following...
ConsoleKeyInfo = ki;
while (true)
{
ki = Console.ReadKey();
if (ki.Key == ConsoleKey.A)
{
//I know the following isn't actually code, but it's explaining what I want to happen.
do (onKeyRelease)
{
Console.Write("A");
}
}
}
Basically, I'm wanting only one thing to happen when the loop when a key is pressed until the key is released. When the key is released, the loop will start again.
Please note that I am using this idea for a Text-Based RPG game. So waiting until another key is pressed (including adding another Console.ReadKey() to the end) would not be ideal.
1st Suggestion - Have you tried "break" the loop when the console has displayed the "A"?
2nd Suggestion -
ConsoleKeyInfo = ki;
var alreadyPressed = false
while (true)
{
ki = Console.ReadKey();
if (ki.Key == ConsoleKey.A && !alreadyPressed)
{
Console.Write("A");
alreadyPressed = true;
}}`
Store last pressed key and print character only when it is different from the last pressed key.
I'm doing a small c# application.
(Press 0 to end the program)
All I know is:
Console.ReadKey(); but that only works when you press ANY key.
But how do you exit an application with just 0?
you don't need to run the while loop to findout the key.
you have to compare with the what ever users enters the key.
ConsoleKeyInfo info= Console.ReadKey();
if (info.KeyChar == 48)
Environment.Exit(0);
else
{ // do your things
}
First of all your program will run in a while loop. Read the entered word and check in if condition that whenever it is 0 or not. If it is 0 then let the program finish by breaking the loop otherwise use continue. Let me know if you have any confusion.
You can use while loop :
ConsoleKeyInfo cki = new ConsoleKeyInfo();
while (cki.Key != ConsoleKey.D0 && cki.Key != ConsoleKey.NumPad0)
{
cki = Console.ReadKey(true);
// your code here
}