On key pressed multiple times - c#

I need to make different commands on Escape key pressed, for example
if Escape key is once pressed .. Draw(250,250);
if Escape key is twice pressed .. Draw(350,350);
if Escape key is triple pressed .. Draw(450,450);
on one key I have to have multiple different commands,
how to make the app to count how many times a key is pressed and using that info .. to run a specific code?

You should create a counter and increment it each time the key is pressed.
If you are talking about double or triple "clicking", you also need to set a Timer.
Each time the timer ends, you reset your counter.
Only thing left is to call the method you want depending on your counter value.
int MyKeyCounter = 0;
Timer CounterResetter = new Timer(1000);
CounterResetter.Elapsed += ResetCounter;
void OnKeyPressEvent(object sender, KeyPressEventArgs e)
{
if (e.Key == Key.Escape)
{
MyKeyCounter++;
if(!CounterResetter.Enabled)
CounterResetter.Start();
}
}
void ResetCounter(Object source, ElapsedEventArgs e)
{
if(MyKeyCounter == 1)
Method1();
else if (MyKeyCounter == 2)
Method2();
...
MyKeyCounter = 0;
}
Attach the event on the control you want and put the fields at the top.

This is the best way I can think of. It waits for the user to input a key, and counts it
if its the escape key. Any other key pressed breaks the loop, then you count the times pressed!
ConsoleKeyInfo key;
int timesPressed = 0;
while(true) {
key = Console.ReadKey();
if (!key.Equals( ConsoleKey.Escape ) || timesPressed >= 3) {
break;
}
timesPressed++;
}

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.

Reset clock when enter key is pressed

I have created a 24 hour clock and I want to be able to reset it to 00:00:00 when the enter key is pressed. The clock itself functions fine but I am unable to include the reset functionality properly
static void Main(string[] args)
{
Clock _clock = new Clock();
ConsoleKeyInfo _key = Console.ReadKey();
while (true)
{
Console.WriteLine(_clock.Time);
_clock.Tick();
System.Threading.Thread.Sleep(1000);
if (_key.KeyChar == (char)13)
{
_clock.Reset();
}
}
The problem is, you only read the current keypress once- at the very beginning of your program. Console.Readkey() will wait for you to press a key, then return the key you pressed (which then gets stored in _key). Because you never read another keypress inside the loop, _key will never change.
Of course, you can't simply call Console.ReadKey() inside the loop or the program will pause and wait for you to press a key during every iteration, so you'll want to follow the advice Aybe linked to in his comment.

RegisterHotkey and loop. break if the certain key pressed

i have a hotkey and if i press that hotkey it will press f1 every 2 seconds and i want it to break the loop if f2 is pressed. can you guys help?
this code doesn't break the loop plz help
public Form1()
{
InitializeComponent();
int id = 0; // The id of the hotkey.
RegisterHotKey(this.Handle, id, (int)KeyModifier.None, Keys.A.GetHashCode());
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);
int id = m.WParam.ToInt32();
int i = 1;
while (true)
{
System.Threading.Thread.Sleep(2000);
SendKeys.Send("{F1}");
if (Control.ModifierKeys == Keys.F2)
{
break;
}
Console.WriteLine(i++);
}
}
}
If you are working on WinForms, you can easily do it with System.Windows.Forms.Timer.
First, place two Timers in your form. (It will automatically goes component area)
One for key checking, one for key pressing
Set Timer.Interval whatever you want (called every N ms)
for example, if you set Timer.Interval to 100, Timer.Tick event will fired every 100ms when Timer is enabled.
Double-click your timer component -> this will create Tick event for you
// timer1 for key checking, recommend you to set interval 10
private void timer1_Tick(object sender, EventArgs e) {
// check key press with GetAsyncKeyState
if (GetAsyncKeyState(Keys.F1) == -32768) {
// disable timer2
timer2.Enabled = false;
}
}
// timer2 for key pressing, recommend you to set interval 2000
private void timer2_Tick(object sender, EventArgs e) {
SendKeys.Send("{F1}");
}
GetAsyncKeyState on MSDN / PInvoke
if you're Korean, you can refer this blog too.
This kind of operation requires unmanaged Windows API's to properly execvute. Both the keyhook and the Keysend are a tricky beasts in themself. I can not help you with that part.
Regardless of that, you require some form of multitasking to pull this off. Your specific case should be solveable with a Timer. Propably even the minimalistic WindwosForms one. 2 seconds delay with a single sendkey is not anywhere close where it's limits become reelvant.
However if you want to learn proper Multitasking, you should consdier using the BackgroudnWorker instead. It is a very good way to learn Multitasking via Multithreading. If you go the route of Multithreading, this is code for rate limiting I once wrote up. Do mind that it must be run in an alternate Thread or adapted for Multitasking without Threads:
integer interval = 20;
DateTime dueTime = DateTime.Now.AddMillisconds(interval);
while(true){
if(DateTime.Now >= dueTime){
//insert code here
//Update next dueTime
dueTime = DateTime.Now.AddMillisconds(interval);
}
else{
//Just yield to not tax out the CPU
Thread.Sleep(1);
}
}

C# Console Loop Proceed On KeyUp

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.

How could i recognize 2 separate key presses as one key?

So for a game i'm working i have a bunch of different keys doing different things (for example w key makes the player look up and the e key makes the character look up right).
I'm wondering is there a way to make the W + the D key make the player look up right, even though those keys are already being used.
private void FrmGM_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.W)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player1));
bulletnumb = 1;
}
if (e.KeyCode == Keys.E)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player2));
bulletnumb = 2;
}
if (e.KeyCode == Keys.D)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player3));
bulletnumb = 3;
}
if (e.KeyCode == Keys.C)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player4));
bulletnumb = 4;
}
if (e.KeyCode == Keys.X)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player5));
bulletnumb = 5;
}
if (e.KeyCode == Keys.Z)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player6));
bulletnumb = 6;
}
if (e.KeyCode == Keys.A)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player7));
bulletnumb = 7;
}
if (e.KeyCode == Keys.Q)
{
picplayer.BackgroundImage = ((System.Drawing.Image)(Properties.Resources.IPT_game_player8));
bulletnumb = 8;
}
this is the code for my keys presses
Store letters in a set when the KeyDown events arrive, and remove them in the KeyUp event handler. This way your KeyDown would be able to "see" if the "companion key" has been pressed:
private readonly ISet<char> keysCurrentlyDown = new HashSet<char>();
private void FrmGM_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.W)
{
if (keysCurrentlyDown.Contains('D')) {
// Call some method to handle W+D
} else {
...
}
keysCurrentlyDown.Add('W');
} else if (e.KeyCode == Keys.D)
{
if (keysCurrentlyDown.Contains('W')) {
// Call some method to handle W+D
} else {
...
}
keysCurrentlyDown.Add('D');
}
...
}
private void FrmGM_KeyUp(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.W) {
keysCurrentlyDown.Remove('W');
} else if (e.KeyCode == Keys.D) {
keysCurrentlyDown.Remove('D');
} ...
}
}
The first line of offense for this sort of thing is just to make sure that each key can be activated concurrently, and that the combination of the effects of each key have the result you want. Your code will be more maintainable and easier to write if you follow that approach, rather than trying to special-case the combine key input.
For example, you can have a set of flags that represent the current key state, and then on your game's frame update, check those flags and set the character state to the correct thing (i.e. instead of setting specific images in the key-handling itself, as you're doing now).
So you could have flags like:
bool lookUp, lookRight, lookDown, lookLeft;
Then key-down for W would set the lookUp flag, while key-up for the same key would clear the flag. Likewise e.g. for D, for the lookRight flag.
Then on your game frame update, you check the flags. If lookUp and lookRight are both set, then you use the "look up and right" graphic. If just one or the other flag are set, then you use the plain "look up" or "look right" graphic. Likewise for other keys and their combinations. You could even resolve lookUp and lookDown, or lookLeft and lookRight, as whatever the default graphic would be (i.e. as if the user pressed no keys).
Note that if you're willing to use p/invoke, you can use the GetAsyncKeyState() function, and not even bother with the key-down event. Just check the key state before each frame update for the game, and update the visuals according to the current keyboard state. That way, you let Windows do all the key state tracking, and you don't waste time tracking key state that doesn't matter (e.g. if the user causes multiple changes to the key state between frames).
That said, if you can't/won't do any of the above, then yes...all you need to do is check for the combination first (i.e. you got the key-down for both, without a key-up for the initially-pressed key of the combination).
Do note that taking that approach means that you will still take the effect for the first key pressed, and then have to switch to the combination effect.
use the
PresentationCore.dll and the
WindowsBase.dll as reference in your project
PresentationCore.dll has a Keyboard - Class and WindowsBase.dll has a Key - Class.
then:
using System;
using System.Windows.Forms;
using System.Windows.Input;
namespace ViewTest
{
public partial class ViewTest : Form
{
private void ViewTest_KeyDown(object sender, KeyEventArgs e)
{
if (Keyboard.IsKeyDown(System.Windows.Input.Key.W) &&
Keyboard.IsKeyDown(System.Windows.Input.Key.D))
{
// do something
}
}
}
it's a simple way to do this :)
Look into overriding the ProcessCmdKey
protected override bool ProcessCmdKey(ref Message m, Keys k)
{
if (k == (Keys.Control | Keys.D))
{
MessageBox.Show("CTRL+D");
return true;
}
return base.ProcessCmdKey(ref m, k);
}

Categories