Disallow console to print any keys and take only arrows as input - c#

I have the following code in a Console Application C#. The problem is if I give any input from keyboard other than Arrows, it prints those characters onto the console. Is there a way to prevent characters other than arrows to be printed on the Console. Also is there a way to enhance the following program.
class Program
{
static ConsoleKeyInfo keyinfo;
// public ConsoleKeyInfo keyinfo;
static void Main(string[] args)
{
do
{
keyinfo = Console.ReadKey();
say();
}
while(keyinfo.Key == ConsoleKey.DownArrow
|| keyinfo.Key == ConsoleKey.UpArrow
|| keyinfo.Key == ConsoleKey.LeftArrow
|| keyinfo.Key == ConsoleKey.RightArrow);
}
public static void say()
{
if(keyinfo.Key == ConsoleKey.DownArrow)
{
Console.WriteLine("Down");
}
else if(keyinfo.Key == ConsoleKey.UpArrow)
{
Console.WriteLine("Up");
}
else if(keyinfo.Key == ConsoleKey.RightArrow)
{
Console.WriteLine("Right");
}
else if(keyinfo.Key == ConsoleKey.LeftArrow)
{
Console.WriteLine("Left");
}
else
{
Console.ReadKey(false);
}
}
}

You have to filter the output to the standart output stream.
The console uses a text writer to output the data coming from the standard input, and this text writer is invoked BEFORE the console gives you the key by Console.ReadKey(), therefore, you cannot cancel the outputting of the characters pressed. BUT!
You can set a custom text writer by Console.SetOut();
The code below sets a text writer which will filter everything. Only the Write(char) method is overridden and it is sufficient as far as I can see, if not, you can implement others.
When you need to actually write to the console, swap the text writer to a default one having standart output stream as the base stream, and voila:
class ConsoleFilteredOutput : TextWriter
{
public override void Write(char value)
{
}
public override Encoding Encoding
{
get { return Encoding.Unicode; }
}
}
static TextWriter standardOutputWriter = Console.Out;
static ConsoleFilteredOutput filteredOutputWriter = new ConsoleFilteredOutput();
static void WriteUnfiltered(string text)
{
Console.SetOut(standardOutputWriter);
Console.WriteLine(text);
Console.SetOut(filteredOutputWriter);
}
static void Main(string[] args)
{
Console.SetOut(filteredOutputWriter);
do
{
ConsoleKeyInfo keyinfo = Console.ReadKey();
switch (keyinfo.Key)
{
case ConsoleKey.DownArrow:
case ConsoleKey.LeftArrow:
case ConsoleKey.UpArrow:
case ConsoleKey.RightArrow:
WriteUnfiltered(keyinfo.Key.ToString());
break;
}
}
while (true);
}
}
`

Related

C# Console.ReadLine creates new line with every keypress

I've encountered this weird issue that might be connected to my IDE or C# overrall.
Whenever I am inputting something in the console that is being read my Console.ReadLine(), it is being duplicated and shown below until I press return. I want to input a whole String for example, but what I see is reading char by char which kind of messes up debugging and presence of my program. I am attaching the code below along with the screenshot of the issue.
using System;
using System.Text.RegularExpressions;
namespace Zadanie_1
{
class Program
{
static void ShowMenu()
{
Console.WriteLine("Witaj w grze Siszarp!");
Console.WriteLine("[1] Zacznij nową grę");
Console.WriteLine("[X] Zamknij program");
}
static void PickOption(ConsoleKeyInfo keyPressed)
{
switch (keyPressed.KeyChar)
{
case '1':
Console.Clear();
Option1Picked();
break;
case 'X':
Environment.Exit(0);
break;
}
}
static bool IsCharacterNameValid(String characterName)
{
if (characterName.Length < 2)
{
Console.WriteLine("Niepoprawna nazwa!");
return false;
}
if (!Regex.IsMatch(characterName, #"^[a-zA-Z]+$"))
{
Console.WriteLine("Niepoprawna nazwa!");
return false;
}
return true;
}
static void EnterCharacterName()
{
String characterName;
do
{
Console.Write("Podaj nazwę bohatera:");
characterName = Console.ReadLine();
} while (!IsCharacterNameValid(characterName));
}
static void Option1Picked()
{
EnterCharacterName();
}
static void Main(string[] args)
{
ShowMenu();
ConsoleKeyInfo keyPressed = Console.ReadKey();
PickOption(keyPressed);
}
}
}

Loop a method call based on user choice

Based on the user choice can we call the method infinitely. If a User presses the Key "Y", call the method, else quit the console app.
Below is the code:
namespace IR_CSharp
{
class Program
{
private void GetASCIIValue()
{
Console.WriteLine("Enter a value to get the ascii value: ");
int value = Console.Read();
Console.WriteLine("ASCII value is {0}", value);
Console.ReadKey();
}
static void Main(string[] args)
{
Program prog = new Program();
string choice = "0";
prog.GetASCIIValue();
}
}
}
class Program
{
static void Main(string[] args)
{
ConsoleKeyInfo keyinfo;
do
{
Console.WriteLine("Enter a value to get the ascii value: ");
int value = Console.Read();
Console.WriteLine("ASCII value is {0}", value);
keyinfo = Console.ReadKey();
}
while (keyinfo.Key != ConsoleKey.Y);
}
}

Copying TextReader/Writer to more places

I have console application that can turn winform with richtextbox. I want to redirect console and that richtextbox to each other. So whenever I write to them text will copy to another. My problem is when I'm waiting for ReadLine. I would like to react to first ReadLine. This is my code:
class ConsoleFormReDirectWriter : TextWriter
{
TextWriter t;
RichTextBox r;
public ConsoleFormReDirectWriter(TextWriter TextWriter, RichTextBox FormOut)
{
t = TextWriter;
r = FormOut;
}
public override void Write(char value)
{
t.Write(value);
RichTextBoxExtensions.AppendText(r, value +"", Color.White);
}
public override void WriteLine(string line)
{
t.WriteLine(line);
RichTextBoxExtensions.AppendText(r, line+"\n", Color.White);
}
public override Encoding Encoding
{
get { return Encoding.Default; }
}
}
class ConsoleFormReDirectReader : TextReader
{
Queue<string> ReadLineQ = new Queue<string>();
public void AddToReadLineQueue(string s)
{
ReadLineQ.Enqueue(s);
}
public override string ReadLine()
{
string line = "";
while (true)
{
if (ReadLineQ.Count != 0) { line = ReadLineQ.Dequeue(); break; }
}
return line;
}
}
Then im handling press enter event on richtext box and apending queue by currentLine. I dont know how to make something similar with console.
or is there a better method of doing same?
PS: i can make new thread that will be asking console for readline in infinite loop, and when readline return something than i can append the queue. But that seems very unefective.
After a while i found semi solution. I used Console.readline with timeout and
now I have my Readline:
public override string ReadLine()
{
bool toConsole=false, toUI=false;
string line = "";
while (true)
{
if (ReadLineQ.Count != 0)
{ line = ReadLineQ.Dequeue();
toConsole = true;
break;
}
try
{
line = DelayReader.ReadLine(50);
}
catch(TimeoutException) { continue; }
toUI = true;
break;
}
if (toConsole) t.WriteLine(line);
if (toUI) RichTextBoxExtensions.AppendText(r, line + "\n", Color.White);
return line;
}
And Console.Readline with delay i foun here: ReadLine(delay)

model view view controller C#

I am writing a simple program in c# which asks the user to enter a number, then tells the user if the number is odd or even. my program works however wheni first enter the number nothing happens, i have to enter the number twice and then it tells me if the number is odd or even, im not very good at using the mvvc technique, so if anyone knows why this is happening and could help me that would be great.my code is below...
class CheckNumber
{
protected String number;
public void SetNumber(String newNumber)
{
number = newNumber;
}
public int Number()
{
int number = Convert.ToInt32(Console.ReadLine());
if (number % 2 == 1) //(number % 2 == 0) would test for even numbers(0 remainder)
{
Console.WriteLine("Odd number");
}
else
{
Console.WriteLine("Even number");
}
return number;
}
}
class CheckNumberController
{
IView view;
CheckNumber checkNumber;
public CheckNumberController(IView theView, CheckNumber theCheckMark)
{
view = theView;
checkNumber = theCheckMark;
}
public void Go()
{
view.Start();
checkNumber.SetNumber(view.GetString("Please enter a number"));
view.Show(checkNumber.Number());
view.Stop();
}
}
class ConsoleView : IView
{
public void Start()
{
Console.Clear();
}
public void Stop()
{
Console.WriteLine("Press any key to finish");
Console.ReadKey();
}
public String GetString(String prompt = "")
{
Console.WriteLine(prompt);
return Console.ReadLine();
}
public Int32 GetInt(String prompt = "")
{
Console.WriteLine(prompt);
return Int32.Parse(Console.ReadLine());
}
public void Show<T>(T message)
{
Console.WriteLine(message);
}
}
interface IView
{
void Start();
void Stop();
String GetString(String prompt);
Int32 GetInt(String prompt);
void Show<T>(T message);
}
class Program
{
static void Main(string[] args)
{
new CheckNumberController(new ConsoleView(), new CheckNumber()).Go();
}
}
You're reading input twice. Firstly in the CheckNumberController.Go()
checkNumber.SetNumber(view.GetString("Please enter a number"));
And secondly in CheckNumber.Number()
int number = Convert.ToInt32(Console.ReadLine());
The latter should be:
int number = Convert.ToInt32(this.number);
As you want to work on the value you've already read and set, not an additional one
public String GetString(String prompt = "")
{
Console.WriteLine(prompt);
//return Console.ReadLine();
return "error is here";
}
When calling GetString() method your again trying to get an input. Just comment and return string if you want.
The key is in this method:
public void Go()
{
view.Start();
checkNumber.SetNumber(view.GetString("Please enter a number"));
view.Show(checkNumber.Number());
view.Stop();
}
SetNumber(string) sets the protected field number in the CheckNumber class. However, when you call view.Show<T>(T), you are calling the Number() method on the CheckNumber class, which ignores the stored variable and reads from the console again.

c# if statement for macro

i am trying to create a macro with jitbit macro recorder, what i need is if statement for shortcuts, like "ctrl+y", but software doesnt have if statement for shourtcuts. But there is Run "C# code" feature. I am trying to create a code for this. but failed so far.Can anyone help me?
Note: code must contain a class named Program with the static method Main.
Here is example code from the macro recorder;
public class Program
{
public static void Main()
{
System.Windows.Forms.MessageBox.Show("test");
}
}
Maybe this is what you are searching for:
class Program
{
static void Main(string[] args)
{
ConsoleKeyInfo keyinfo;
do
{
keyinfo = Console.ReadKey(true);
if (keyinfo.Modifiers == ConsoleModifiers.Control)
{
if (keyinfo.Key == ConsoleKey.Y)
{
// Do something
}
else if (keyinfo.Key == ConsoleKey.Z)
{
// Do something else
}
}
}
while (keyinfo.Key != ConsoleKey.X); // Ends the program if you press X
}
}

Categories