How to handle key press event in console application - c#

I want to create a console application that will display the key that is pressed on the console screen, I made this code so far:
static void Main(string[] args)
{
// this is absolutely wrong, but I hope you get what I mean
PreviewKeyDownEventArgs += new PreviewKeyDownEventArgs(keylogger);
}
private void keylogger(KeyEventArgs e)
{
Console.Write(e.KeyCode);
}
I want to know, what should I type in main so I can call that event?

For console application you can do this, the do while loop runs untill you press x
public class Program
{
public static void Main()
{
ConsoleKeyInfo keyinfo;
do
{
keyinfo = Console.ReadKey();
Console.WriteLine(keyinfo.Key + " was pressed");
}
while (keyinfo.Key != ConsoleKey.X);
}
}
This will only work if your console application has focus. If you want to gather system wide key press events you can use windows hooks

Unfortunately the Console class does not have any events defined for user input, however if you wish to output the current character which was pressed, you can do the following:
static void Main(string[] args)
{
//This will loop indefinitely
while (true)
{
/*Output the character which was pressed. This will duplicate the input, such
that if you press 'a' the output will be 'aa'. To prevent this, pass true to
the ReadKey overload*/
Console.Write(Console.ReadKey().KeyChar);
}
}
Console.ReadKey returns a ConsoleKeyInfo object, which encapsulates a lot of information about the key which was pressed.

Another solution, I used it for my text based adventure.
ConsoleKey choice;
do
{
choice = Console.ReadKey(true).Key;
switch (choice)
{
// 1 ! key
case ConsoleKey.D1:
Console.WriteLine("1. Choice");
break;
//2 # key
case ConsoleKey.D2:
Console.WriteLine("2. Choice");
break;
}
} while (choice != ConsoleKey.D1 && choice != ConsoleKey.D2);

Related

How to use Console.ReadKey() while avoiding the same key being registered constantly after, C#

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.

Is there a way to get an input in the console without having to press the enter key?

I want to be able to get single characters from the console without having to press the enter key.
For example, when I press the letter "e", I want to immediately use that value without the user having to press the enter key
Try:
var key = System.Console.ReadKey(intercept: true);
The intercept flag prevents the pressed key from being rendered into the terminal.
What yoy need is Console.ReadKey().
For example:
ConsoleKeyInfo key = Console.ReadKey(); // Read pressed key
char c = key.KeyChar; // char...
string s = c.ToString(); // ... or string, depending on what you need.
As already suggested, you can try type Console. in VS and see which members are available.
Hope this is what you are looking for!
Reference: How to handle key press event in console application
using System;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press 'Shift+Q' to exit.");
do {
ConsoleKeyInfo keyInfo = Console.ReadKey(true);
if (keyInfo.Modifiers.HasFlag(ConsoleModifiers.Shift)
&& keyInfo.Key == ConsoleKey.Q)
{
break;
}
// TODO : Write your code here
Console.WriteLine(keyInfo.KeyChar);
} while (true);
}
}
}

Why doesn't void Main start after the if-condition?

Void Main won't start again after the if-statement.
I have been experimenting for a while with such constructions and normally they work. But that's not the case. The generator void is somewhere below, please don't take it into consideration.
class Program
{
private static string Input = Console.ReadLine();
static void Main()
{
Console.WriteLine("Press any key to start");
Program.Generator();
Console.WriteLine("Are you satisfied? Type '1' if yes or '2' if no.");
Console.ReadLine();
if (Input == "2")
Program.Main();
}
}
No errors, no mistakes, the console just closes after completing Main.
Welcome to stack overflow. You're not crazy, just missing a piece of information about programming and flow of control. Specifically, iteration statements.
The program you've written will exit any time Input holds a value other than 2 because there's no loop forcing it to run over and over again.
static void Main()
{
Console.WriteLine("Press any key to start");
Console.ReadKey();
do
{
// Program.Generator();
Console.WriteLine("Are you satisfied? Type '1' if yes or '2' if no.");
} while (Console.ReadKey().KeyChar != '1');
}

C# My while loop repeats 3 times before it prompts for another choice

I am new to C# but I know Java pretty well. I may be missing something simple that I am just not aware of because of being new to this particular language. I am trying to make a while loop that repeats until the user chooses Q. The loop exits fine but the code inside are repeated 3 times before it stops to prompt the user for a choice. Why would this happen?
class MainClass
{
public static void DisplayMenu() {
Console.WriteLine("What would you like to do?");
Console.WriteLine("(D)eposit");
Console.WriteLine("(W)ithdraw");
Console.WriteLine("(C)alculateInterest");
Console.WriteLine("(S)howBalance");
Console.WriteLine("(Q)uit");
Console.WriteLine("************************************");
Console.WriteLine("Make choice by entering first letter of choice,");
Console.WriteLine("then press ENTER key:");
}
static void Main(string[] args) {
Account account = new Account();
char choice;
double amount = 0.0;
Console.WriteLine("************************************");
Console.WriteLine("Welcome to Bernard's Bodacious Bank!");
Console.WriteLine("************************************");
Console.WriteLine("We have opened your account");
DisplayMenu();
choice = Char.ToUpper((char)Console.Read());
while (!choice.Equals('Q')) {
DisplayMenu();
choice = Char.ToUpper((char)Console.Read());
}
account.ShowTransactions();
Console.ReadKey();
}
}
The reason is likely because you are using Console.Read(), which will process the next character in the input stream, which includes the \n and \r characters from when the user pressed Enter. These characters are then immediately processed inside your loop on the calls to Console.Read().
If you just want a single character, you could instead use Console.ReadKey(), which returns the first key (as type ConsoleKeyInfo) that the user types. You can then do a comparison on it's Key property like:
Console.WriteLine("************************************");
Console.WriteLine("Welcome to Bernard's Bodacious Bank!");
Console.WriteLine("************************************");
Console.WriteLine("We have opened your account");
double amount = 0.0;
ConsoleKeyInfo choice;
do
{
DisplayMenu();
choice = Console.ReadKey();
} while (choice.Key != ConsoleKey.Q);
Alternatively, if you DO want to allow them to press enter, then you should use the Console.ReadLine() method and check to see what it StartsWith:
DisplayMenu();
string choice = Console.ReadLine();
while (!choice.StartsWith("Q", StringComparison.OrdinalIgnoreCase))
{
DisplayMenu();
choice = Console.ReadLine();
}
Here's an example of how you might process input. It assumes you have methods that can be called for each choice:
var quit = false;
while(!quit)
{
DisplayMenu();
var choice = Console.ReadKey();
switch (choice.Key)
{
case ConsoleKey.D:
Deposit();
break;
case ConsoleKey.W:
Withdrawl();
break;
case ConsoleKey.C:
CalcInterest();
break;
case ConsoleKey.S:
ShowBalance();
break;
case ConsoleKey.Q:
quit = true;
break;
default:
Console.WriteLine("Invalid entry, try again");
break;
}
}
From the MSDN documentation:
The Read method blocks its return while you type input characters; it terminates when you press the Enter key. Pressing Enter appends a platform-dependent line termination sequence to your input (for example, Windows appends a carriage return-linefeed sequence). Subsequent calls to the Read method retrieve your input one character at a time. After the final character is retrieved, Read blocks its return again and the cycle repeats.
In Windows, a "platform-dependent line termination sequence" is equal to \r\n. So when you type A, then Enter, you are actually sending 3 keystrokes for your program to process.
Also from the MSDN documentation:
The ReadLine method, or the KeyAvailable property and ReadKey method are preferable to using the Read method.
This seems to be the simplest answer, Use the read key method then use the choice.Key and ConsoleKey.Q. Thanks for the help though guys! It pointed me in the right direction!
static void Main(string[] args) {
Account account = new Account();
double amount = 0.0;
ConsoleKeyInfo choice;
Console.WriteLine("************************************");
Console.WriteLine("Welcome to Bernard's Bodacious Bank!");
Console.WriteLine("************************************");
Console.WriteLine("We have opened your account");
DisplayMenu();
choice = Console.ReadKey();
while (choice.Key != ConsoleKey.Q) {
switch (choice.Key) {
case ConsoleKey.D:
Console.WriteLine("found d!");
break;
default:
Console.WriteLine("Input Error!");
break;
}
}
account.ShowTransactions();
Console.ReadKey();
}

How do I nullify (or assign another value to) a System.ConsoleKey value once it's finished being used?

I have a repeating code here, full of goto statements that make this while loop well... Repeat forever.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test
{
class Program
{
static void Main(string[] args)
{
main();
}
public static ConsoleKeyInfo keyPressed;
private static void main()
{
start:
keyPressed = Console.ReadKey();
while (true)
{
loopstart:
if (keyPressed.Key == ConsoleKey.Enter)
{
Console.WriteLine("You pressed the Enter Key!");
goto loopstart;
}
if (keyPressed.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed the Escape Key!");
goto loopstart;
}
if (keyPressed.Key == ConsoleKey.Spacebar)
{
Console.WriteLine("You pressed the Spacebar!");
goto loopstart;
}
else
{
break;
}
}
Console.WriteLine("You broke the loop!");
goto start;
}
}
}
Without removing any code, is it possible to change the value of keyPressed.Key or keyPressed itself to NULL; the state it was when it was declared, or to any other value/key that's not the spacebar, enter or escape key?
Of course, the problem could be solved by removing all the goto loopstart; in the code, but that's against the point of the question.
What I want to do is make the keyPressed.Key value NULL (or any other value) so that all the IF statements will result in false, which therefore means not running the goto loopstart code.
The problem now is that when I try to nullify it with a simple keyPressed = null;, it comes with the error of:
Cannot convert null to 'System.ConsoleKeyInfo' because it is a non-nullable value type.
Is there any way I can nullify (or change the value to something else) so that I can break the loop?
(As in: Make the IF statement get to the point where it has to run the else code)
It should look something like:
...
{
loopstart:
if (keyPressed.Key == ConsoleKey.Enter)
{
Console.WriteLine("You pressed the Enter Key!");
// keyPressed = null; <-- Does not work.
// Do something to make ConsoleKey.Key to equal something else.
goto loopstart;
}
if (keyPressed.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed the Escape Key!");
...
Obviously with the // Do something to make ConsoleKey.Key to equal something else. replaced with working code?
If this works, the first time the loop runs (presuming the key pressed at the start is either the Spacebar, Escape or Enter keys) would result with the goto loopstart; being used, and the second time round would skip through to the goto start; where it'll ask for another key.
And then the process repeats at the speed of which the user gives an input, rather than repeating with the same key without stop, or asking for another key.
Basically: Make the loop run the IF statement as a proper IF statement instead of a FOR loop.
See also
Why use goto-statement, it's very outdated constructure. You can easily continue the loop. And else check is also redundant. You can simply read the key from Console before check, like this:
while (true)
{
keyPressed = Console.ReadKey();
switch (keyPressed.Key)
{
case ConsoleKey.Enter:
Console.WriteLine("You pressed the Enter Key!");
continue;
case ConsoleKey.Escape:
Console.WriteLine("You pressed the Escape Key!");
continue;
case ConsoleKey.Spacebar:
Console.WriteLine("You pressed the Spacebar!");
continue;
}
// should be outside the switch for breaking the loop
break;
}
If you want to clear keyPressed, use default construction, like this:
keyPressed = default(ConsoleKeyInfo);
But why do you want to do this? Garbage Collection will clear the memory by itself, you should not go into there.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test
{
class Program
{
static void Main(string[] args)
{
main();
}
public static ConsoleKeyInfo keyPressed;
private static void main()
{
start:
keyPressed = Console.ReadKey();
while (true)
{
loopstart:
if (keyPressed.Key == ConsoleKey.Enter)
{
Console.WriteLine("You pressed the Enter Key!");
keyPressed = new ConsoleKeyInfo('a', ConsoleKey.A, false, false, false);
goto loopstart;
}
if (keyPressed.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed the Escape Key!");
goto loopstart;
}
if (keyPressed.Key == ConsoleKey.Spacebar)
{
Console.WriteLine("You pressed the Spacebar!");
goto loopstart;
}
else
{
break;
}
}
Console.WriteLine("You broke the loop!");
goto start;
}
}
}

Categories