3

This question is a bit obscure, however I cannot find an answer for it anywhere. I am writing a program in C# (Visual Studio Pro 2013) and I need to perform an action after the user has stopped typing for 2 seconds (setting the interval at 2000). I would need a standard timer for this however I need to detect when the user has stopped typing for 2 seconds. How would I go about doing this?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
carefulnow1
  • 803
  • 12
  • 30
  • If it is useful I need to also say that I am using WinForms and not WPF. – carefulnow1 Dec 27 '14 at 20:01
  • 5
    Start a timer on each keystroke. If the timer beats the next keystroke then you have a sleeping typist. If the next keystroke beats the timer then reset the timer for another 2 seconds. – HABO Dec 27 '14 at 20:04
  • 1
    put the code that you try... – Mohamad Shiralizadeh Dec 27 '14 at 20:07
  • HABO would the timer be started when the program is first executed? – carefulnow1 Dec 27 '14 at 20:10
  • You need just one event after the user stopped to type or every 2 seconds you need to be informed of its inactivity? – Steve Dec 27 '14 at 20:28
  • Does a user failing to type in the first two seconds after the program starts constitute an event? If so, you need to start the timer when the program starts. If you only care that they continue typing after they've started typing then you only need to start the timer after the first keystroke. – HABO Dec 27 '14 at 20:36
  • possible duplicate of [Detecting idle users in Winforms](http://stackoverflow.com/questions/6282298/detecting-idle-users-in-winforms) – TFD Dec 27 '14 at 20:53
  • I am aware this question is a possible duplication of the above post however this is a very specific issue... not bothering with mouse detection. – carefulnow1 Dec 27 '14 at 21:01

5 Answers5

2

Here's the complete code:

public partial class Form1 : Form
{
    System.Timers.Timer timer;

    public Form1()
    {
        InitializeComponent();

        // Initialize the timer.
        timer = new System.Timers.Timer();
        timer.Interval = 2000; // = 2 seconds; 1 second = 1000 miliseconds
        timer.Elapsed += OnElapsed;
    }

    // Handles the TextBox.KeyUp event.
    // The event handler was added in the designer via the Properties > Events > KeyUp
    private void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
    {
        // Reset the timer on each KeyUp.
        timer.Stop();
        timer.Start();
    }

    private void OnElapsed(object source, ElapsedEventArgs e)
    {
        // When time's up...

        // - stop the timer first...
        timer.Stop();

        // - do something more...
        MessageBox.Show("Time out!");
    }        
}
t3chb0t
  • 16,340
  • 13
  • 78
  • 118
  • 1
    Surely you need to attach the event to the forms keyboard hook event, not a single control? – TFD Dec 27 '14 at 20:50
  • @TFD: you're right. I should have writtten that I haven't pasted the designer generated code or I should have just wire the `TextBox` here. – t3chb0t Dec 27 '14 at 21:01
  • 1
    This is exactly what I do - though I wrap the `Timer` class in a custom `WatchdogTimer` class with with a bool `AutoRestart` property and a methods for `Start`, `Stop`, and `Restart` so it reads well and the intentions are clear for the reader. – Anthony Dec 29 '14 at 14:56
0

Try this:

System.Timers.Timer timer = new System.Timers.Timer(2000);;
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Enabled = false;

private void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
    timer.Enabled = false;
    timer.Enabled = true;   
}

private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // Do something
    timer.Enabled = false;
}
ChriPf
  • 2,700
  • 1
  • 23
  • 25
dario
  • 5,149
  • 12
  • 28
  • 32
  • 1
    This will fire 2 seconds after the first key-up. Just because a new Timer-object is assigned to the field the "old" one still will exist and fire. Even worse: as the event handler stands assign, the now seemingly no-more-referenced timer objects will never be subject of garbage collection! – ChriPf Dec 27 '14 at 20:13
  • To editet version: this is better (at least avoiding the garbage collection problem). You however should reset the timer on each keyup first, otherwise this will still fire after 2 seconds still. – ChriPf Dec 27 '14 at 20:22
  • `timer.Enabled = true` = `timer.Start()` and `timer.Enabled = false` = `timer.Stop()` [MSDN](http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.enabled%28v=vs.110%29.aspx). Anyway thanks for your comments. – dario Dec 27 '14 at 20:25
  • Who restart the timer after the first event if I stop to type? – Steve Dec 27 '14 at 20:26
  • I am aware of that. Still the first key-up will start the timer and the `timer.Enabled = true` or `timer.Start()` does not restart it in IMO. – ChriPf Dec 27 '14 at 20:28
0

king.code's answer would be correct if you just reset the timer in the first line of textBox1_KeyUp event and initialize the timer in constructor or main method depending on usage.

System.Timers.Timer timer;

private void textBox1_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e)
{
    timer.Stop();
    timer.Start();
    timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
}

private static void OnTimedEvent(object source, ElapsedEventArgs e)
{
    // Do something
}

I would recommend you go for class that inherits text box and pass timer into it if you are going to use it at multiple places

stripathi
  • 766
  • 11
  • 23
  • 1
    I don't think it's a good idea to attach another event handler on each `KeyU`p... you'll end with multiple event handlers. – t3chb0t Dec 27 '14 at 20:23
  • Better but still incorrect and with an exception waiting to happen. timer is not intialized, and Start before the Elapsed? – Steve Dec 27 '14 at 20:23
  • While this might work in principle, still the event handler is assigned on each key up, which might cause funny results. – ChriPf Dec 27 '14 at 20:24
  • Would it have to be _KeyUp becuase I am currently using _KeyPress? – carefulnow1 Dec 27 '14 at 20:25
  • @odixon I'm afraid you'll have to decide yourself which event is better in your case, see this question: [Difference between the KeyDown Event, KeyPress Event and KeyUp Event in Visual Studio](http://stackoverflow.com/questions/5871383/difference-between-the-keydown-event-keypress-event-and-keyup-event-in-visual-s) – t3chb0t Dec 27 '14 at 21:11
  • I have already solved this problem using the KeyPress event, however I will look at that question for future problems. Thankyou t3chb0t. – carefulnow1 Dec 27 '14 at 21:13
0

That is easy just create a timer that sets to 2000 Ms and handle It by the text change interveral . Ex: Set an integer that count from 0 to 2000 then increase it by the Timer if user starts typing then reset the number else keep Counting till reach 2000 an ping do the rusty homeboy helped;)

MH Mazen
  • 91
  • 1
  • 12
0

I have just found a valid answer that is simple and compact. I will explain it first and then show a code example. You need to start the timer disabled, and then you need to enable it as soon as the the user presses a key. Then, while still in the method for the user pressing the button you would need to reset the timer interval back to 2000. Whenever the timer expires, you do the action that needs to happen when the keyboard has been inactive for 2 seconds. Code example:

private void textBox_KeyPress(object sender, KeyPressEventArgs e)
{
    this.timer.Enabled = true;
    this.timer.Interval = 2000;
}

Now the method for the timer_Tick:

 private void timer_Tick(object sender, EventArgs e)
 {
    //Do something when the keyboard has been inactive in 2 seconds
 }
carefulnow1
  • 803
  • 12
  • 30