I want to measure time (seconds) when a user presses the right arrow key on the keyboard and pick it up.
I have researched about this and find some page but there is not a good answer.
How can I measure this time?
my code
I define a List in top of class:
List<int> date_down = new List<int>();
when user press right arrow key : (in Form_KeyDown method)
if (Keyboard.IsKeyDown(Key.Right))
{
date_down.Add(DateTime.Now.Second);
}
when user press right arrow key and held down times Add into list
when user pick up key (in Form_keyUp method)
if (e.Key == Key.Right)
{
var second = DateTime.Now.Second - date_down[0];
}
This may be an alternative
using System.Diagnostics;
using System.Windows.Forms;
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
var watch = new Stopwatch();
KeyDown += (s, e) => watch.Start();
KeyUp += (s, e) => {
watch.Stop();
var elapsed = watch.ElapsedMilliseconds; // Duration
watch.Reset();
};
}
}
Your code is a good start, though you might need to alter it a bit to see it working.
private void form1_KeyDown(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.Key == Key.Right)
{
date_down = DateTime.Now;
}
e.Handled = true;
}
private void form1_KeyUp(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
if (e.Key == Key.Right)
{
var timeDelta = DateTime.Now - date_down;
}
}
You can also trigger a timer from this if you want, instead of grabbing current time and evaluating.
You could start with looking up various classes for measuring time in C#, such as this one.
You will also need a class for detecting key down and key up. Perhaps this might help.
Beyond this, the implementation should be fairly simple. Start the timer when the key is pressed down, stop the timer when the key is released, and use that time as the measurement between when the two events.
Related
So what im looking to do is find if i have the space bar pressed at all and while it is i would like to have the space bar be released and then pressed again mutiple times with a delay of about 10 ms. i have tried to read and understand this link (https://msdn.microsoft.com/en-us/library/system.windows.forms.control.keypress.aspx) but it is still confusing any help? im brand new to c# but i have some experience with pascal of which i have found very similar
(using visual studio 2015 due to my computer not allowing me to update to windows 8.1)
10ms delay mean 100 times per second, no one could do it.
Key events occur in the following order:
KeyDown
KeyPress
KeyUp
Events KeyDown and KeyUp use KeyEventArgs, while KeyPress is KeyPressEventArgs,
KeyEventArgs could details how many keys are pressed at same time. KeyEventArgs.KeyCode is Keys which is a [Flags] enum, it could contains multiple keys, like CTRL+SHift+F+G
if your hotkey is Ctrl+Shift+Space, you can check with:
var hotkeyPressed = e.Control && e.Shift && e.KeyCode == Keys.Space;
if your hotkey is Ctrl+F10+Space, you can check with:
var hotkeyPressed = e.Control && e.KeyCode == (Keys.Space | Keys.F10);
but do not use:
var hotkeyPressed = e.Control && e.KeyCode.HasFlag(Keys.F10) && e.KeyCode.HasFlag(Keys.Space); // e.KeyCode probably contains other flags
KeyPressEventArgs.KeyChar is a string, take a look source code, focus on its comments
[ComVisible(true)]
public class KeyPressEventArgs : EventArgs
{
...
/// <summary>Gets or sets the character corresponding to the key pressed.</summary>
/// <returns>The ASCII character that is composed. For example, if the user presses SHIFT + K, this property returns an uppercase K.</returns>
public char KeyChar { get; set; }
...
}
to use which event, it depends on your requirement.
here is sample code in KeyDown:
private int counting = 0, limit = 10;
private void txt_KeyDown(object sender, KeyEventArgs e)
{
if (!e.KeyCode.HasFlag(Keys.Space)) //check if your expected key is pressed
{
counting = 0;
return;
}
//start counting
counting++;
if (counting > limit)
{
e.Handled = true;
//do you business work, like: Send something somewhere
}
else
{
//do something else, like: show the number 'counting' in GUI
}
}
if you want limit timespan with next space, use a Timer
private void txt_KeyDown(object sender, KeyEventArgs e)
{
timer1.Stop();
if (!e.KeyCode.HasFlag(Keys.Space))
{
counting = 0;
return;
}
//start counting
timer1.Start();
counting++;
if (counting > limit)
{
e.Handled = true;
//do you business work, like: Send something somewhere
}
else
{
//do something else, like: show the number 'counting' in GUI
}
}
//timer1.Interval = 100; //100ms timeout. user has to press space again within 100ms
private void timer1_Tick(object sender, EventArgs e)
{
counting = 0;
}
I am making a simple calculator app where the DEL button removes the last digit in the viewport, but if held down for one second it deletes everything in the viewport. Right now If I press the button once, it deletes the last digit whether I hold it down or not. If I press it down again (held down or just a regular tap) it clears everything in the viewport and I cannot type anything else in.
Firstly I create the timer like so:
public System.Timers.Timer timer = new System.Timers.Timer(1);
and then I have a function for when the 'DEL' button is pressed:
private void DeletePressed(object sender, EventArgs args)
{
timer.Stop();
timer.Start();
timer.Elapsed += AllClear;
}
a function to stop the timer and delete the last character from the viewport when the button is released:
private void DeleteReleased(object sender, EventArgs args)
{
timer.Stop();
if (CalculatorString.Length > 0)
{
CalculatorString = CalculatorString.Remove(CalculatorString.Length - 1);
}
viewport.Text = CalculatorString;
}
and finally the procedure that is called when the timer finishes:
private void AllClear(Object Source, System.Timers.ElapsedEventArgs e)
{
timer.Stop();
CalculatorString = "";
viewport.Text = CalculatorString;
}
however none of what I expected tohas happened. I appreciate any help in advance :)
There is no direct way to listen long press in Xamarin.Forms(PCL). You have to write separate custom renderers for each platform to Listen long press and communicate it to the PCL.
You can refer this link for code example for doing the same.
Sometimes keys up down are not working on DataGridView.
I have no clue why and especially it is weird because there is no code assigned to key's events of DataGridView...
SelectionMode is FullRowSelect
Multiselect is False
This code dos not help...
private void dataGridView1_PreviewKeyDown(object sender, reviewKeyDownEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Down:
e.IsInputKey = true;
break;
case Keys.Up:
e.IsInputKey = true;
break;
}
}
private void dataGridView1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyData == Keys.Down)
{
e.Handled = true;
}
else if (e.KeyData == Keys.Up)
{
e.Handled = true;
}
}
Any clue?
P.S.
It seems like the SelectionChanged method does some hard work... So When I disable it eberything is fine.
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
// Some hard work
}
So the quesion is how to optimize it.
I assume to use Timer so when user stops select arrows keys 1 second later
code of the SelectionChanged method should be executed.
Any clue about the best way to do it?
Somehow during of executing SelectionChanged the grid losts its focus.
And probably it is happening because of the creation and inserting User Controls on fly.
So I did three adjustments and now it is fine!
bool canDoHardWork = true;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (canDoHardWork)
{
int interval = 2000; // Just 2 seconds
Task.Factory.StartNew(() =>
{
canDoHardWork= false;
Thread.Sleep(interval);
this.BeginInvoke((Action)(() =>
{
PopulateTabs(); // Very hard work
dataGridView1.Focus();
canDoHardWork= true;
}), null);
});
}
}
Notice that when you PopulateTabs() you then have to set the Focus back to the DataGridView again. This was your problem with the Up and Down arrow keys. The events for the keys were being caught by your custom control(s). As for the very hard work (PopulateTabs), I notice you're using asynchronous threading with the TPL. Have you thought of doing away with the sleep interval as it seems redundant just set your DoesHardWork variable and change the focus to the DataGridView outside the Task. The reason it is working the way it does at the moment is that the SelectionChanged event fires twice the first time it "DoesHardWork" the second time it falls through as DoesHardWork is still false while it is processing the PopulateTabs(). A more elegant solution would be to set the CellValue/RowValue/Control which is generated by PopulateTabs() to the Object you would return from PopulateTabs() using IAsyncResult.
Something Like This :
bool canDoHardWork = true;
private void dataGridView1_SelectionChanged(object sender, EventArgs e)
{
if (canDoHardWork)
{
IAsyncResult result;
Task.Factory.StartNew(() =>
{
canDoHardWork = false;
result = this.BeginInvoke((Func<Button>)(() =>
{
canDoHardWork = true;
return PopulateTabs(); // Very hard work
}), null);
this.dataGridView1.Controls.Add((Button)this.EndInvoke(result));
dataGridView1.Focus();
});
}
}
There's no need to wait for the thread to complete as when it does it will just add the custom control to the DataGridView and return the control to the main thread. The thread sleep in your example would occur on the asynchronous thread and is as such redundant. In this example the heavy lifting is performed on another thread leaving the main thread free to continue accepting input. Have to put the focus for the DataGridView after the addition of the control or the focus won't change when it needs to.
Maybe its to late but in my problem, using e.Handled = true is the problem.
Put wisely where the command should placed for.
Example :
If on event Key Down, and every Key Enter that user press you want the selected row dont move down and you use the event e.Handled. Put that command like this :
if (e.KeyCode == Keys.Enter)
{
e.Handled = true;
//Do the command
}
Dont use outside the if condition because it will freeze the selected row no matther what key that user press.
In your case, using e.Handled inside Up and down Key Press event just makes it worst, cause every time user press the key, the selected row wont move Up or Down cause with the command e.Handled, you command the program to not move the cursor from the selected row.
Sorry for my bad english...
I have the following code, which on key press, starts moving the two labels from top of the form to the bottom, and after reaching the bottom of the form, it stops. I have done it using the timer. Here is the code
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
label1.Text = "Key Pressed: " + e.KeyChar;
//animate(sender, e);
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
Random random = new Random();
int X = random.Next(0, 1230);
int y = X;
label2.Location = new Point(X, 5);
label3.Location = new Point(X + 20, 5 + 20);
for (int i = 5; i <= 470; i++)
{
label2.Location = new Point(y, i);
label3.Location = new Point(y + 20, i + 20);
Thread.Sleep(1);
}
timer1.Stop();
}
Now during the animation (from the top of the form to the bottom), when I press the key, the animation restarts after reaching the bottom i.e. it completes the tick event and then and only then starts over or stop.
Now what I want is that whenever, during this movement of the labels from the top to bottom i.e. during the tick, if I press any key (or any specific key), the timer should stop.
In short, during the Timer1_Tick method, I want it to stop immediately on a key press.
I tried but couldn't get it to work. I hope that you folks here would help me sort this issue out and hope that you reply on your earliest. Thank you for your time!
The problem here is that you are not really using the Timer in the way that it's intended to be used. Ideally you would have an event that makes a change every time the tick event fires for a Timer.
Here you listen to the event and do several rounds of processing without ever returning from the handler at which point you stop the timer. This means the code will only ever process the tick event once instead of N times.
To fix this try breaking up the handler to do incremental work once per tick and only stop once the drawing is complete. This will also allow you to handle key events in between the tick events and stop the timer. The best place to break up the work is at the Thread.Sleep call (which itself should not appear in the handler)
Try it is so simple
Public Boolean tick = false;
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
tick = !tick;
label1.Text = "Key Pressed: " + e.KeyChar;
//animate(sender, e);
if(tick)
timer1.Start();
else
timer1.Stop();
}
First of all i recommend you to use keyDown and keyUp events instead of key press. To solve your problem: simple set a bool = true on keyDown and and the bool = false on keyUp. Now you can check the bool within you tick method and do whatever you want if you detect key is being pressed.
I am new to C#, and I have searched I but didn't find a simple solution to my problem.
I am creating a Windows form application.
After the start button is clicked, it counts every millisecond and when it reaches specific values from an array changes a label.
How can milliseconds be counted?
-------------------------
AlekZanDer Code:
namespace timer_simple3
{
public partial class Form1 : Form
{
long result = 0;
public Form1()
{
InitializeComponent();
this.timer1 = new System.Windows.Forms.Timer(this.components);
}
private void Form1_Load(object sender, EventArgs e)
{
this.timer1.Tick += new System.EventHandler(this.timer1_Tick);
}
private void timer1_Tick(object sender, EventArgs e)
{
result = result + 1;
label1.Text = Convert.ToString(result);
}
private void btstart_Click(object sender, EventArgs e)
{
timer1.Interval = 1; //you can also set this in the
//properties tab
timer1.Enabled = true;
timer1.Start();
// label1.Text = Convert.ToString(timer1);
}
private void btstop_Click(object sender, EventArgs e)
{
timer1.Stop();
}
}
}
How can milliseconds be counted?
You can't do that, because Windows Forms Timer component is single-threaded, and is limited to an accuracy of 55 milliseconds. If you require a multithreaded timer with greater accuracy, use the Timer class in the System.Timers namespace.
Also any other timer will not give you accuracy more than 16 milliseconds (actually 15.625 milliseconds, or 64Hz). So, you can't increment some counter to count elapsed milliseconds.
Option for you - instead of long result counter use difference between current time and time of timer start:
label1.Text = (DateTime.Now - startDateTime).Milliseconds.ToString();
First you have to create a method that tells the timer what to do every [put the needed number here] milliseconds.
private void randomTimer_Tick(object sender, EventArgs e)
{
if (conditions)
{
... //stuff to do
... //more stuff to do
... //even more stuff to do
}
}
Then you set the timer to call this method: you can do this by using the events tab of the properties of the timer or write:
this.randomTimer1.Tick += new System.EventHandler(this.randomTimer1_Tick);
in the ProjectName.Designer.cs file in the private void InitializeComponent(){} method after the line this.randomTimer = new System.Windows.Forms.Timer(this.components);.
And lastly you enable the timer:
private void startButton (object sender, EventArgs e)
{
randomTimer.Interval = timeInMilliseconds; //you can also set this in the
//properties tab
randomTimer.Enabled = true;
}
Of course, you will have to set the button to call this method too.
If you don't know where the Properties window is (I assume that you are using Visual C#): it's usually a tab located on the right side of the window. In order something to appear in the tab, you have to select the form you want to edit in the design view. If there is no such tab anywhere in the window of the compiler, go to "View" -> "Other Windows" and select "Properties Window".
If the answers you have found are long and complicated, that's mostly because they are explaining the whole process with details and examples. If you use the "drag and drop" option of Visual C#, the declaration code of the forms will happen automatically, afterwards it's up to you to write the code of the methods. There are also other features that are self explanatory and make programming more pleasant. Use them!