Click here to Skip to main content
11,930,843 members (60,042 online)
Click here to Skip to main content
Add your own
alternative version


154 bookmarked

Application Idle

, 2 Mar 2009 CPOL
Rate this:
Please Sign up or sign in to vote.
A WinForms component to notify when your app has been idle for a specified timespan.


I recently needed to have an automatic, timed user-log-out facility in an application. I couldn't find any built-in components, so I 'Googled'. I found various suggestions but the only decent ones worked on activity system wide, not just within the application in use, so I set about writing my own. What I wanted was any key strokes or mouse movements within my application would keep the user logged in, but if none were detected for a pre-defined period, then the user would be automatically logged out.

Rejected Ideas

.NET has an event that initially looked promising, System.Windows.Forms.Application.Idle. Combined with a timer, I thought it would be the solution, but it was not suitable as there is no control over what interrupts it. For example, the timer itself causes the idle state to be exited, which makes perfect sense, of course, but excludes it for this scenario. The next obvious thing was to process key and mouse events on the main form. I rejected this as well as it would have required these to be handled individually for all controls etc... a maintenance nightmare.


In the end, I opted to use IMessageFilter's PreFilterMessage method, not to actually filter any messages, but to get notification of the ones I was interested in. This, combined with a timer, gave the functionality I needed. For convenience, I've wrapped these up into a component that you can drop onto your app's main form.

The Component

The ApplicationIdle component is very simple to use. Documentation is below but I'll cover the basics here.
This second version adds more functionality to the original but can be used in the same way. Drag it onto your form and it will appear in the component bar below the form (or just create an instance of it in your code). Set the IdleTime as required, subscribe to the Idle event and call the Start method. When the application has had no mouse or keyboard activity for the time you specified, your Idle event handling method will be raised.

The Code

The code is built around a TimeSpan _TimeRemaining that is decremented on each tick of a System.Windows.Forms.Timer timer.

The Start method sets the remaining time to the IdleTime's value, registers the component to receive application Windows Messages and starts the internal timer.

public void Start()
    if (!_IsRunning)
        _TimeRemaining = _IdleTime;
        _TimeElapsed = ZeroTime;
        _IsRunning = true;

You will notice two OnEvent methods are called at the end of this method. All the behavior events have two versions - a standard synchronous and an asynchronous one. This is in response to comments that were made on the first version.

Normally we raise events synchronously. In other words, the event doesn't return until all subscribers have done their thing in their handlers. If you decided to do something time intensive in one of your event handlers, it would block the component which isn't ideal for something that is time based like this. The answer is to raise the event asynchronously on a separate thread. The downside is, the event handling method must handle the threading properly if for example it is going to update the UI.

This is an example of how the StartedAsync event may be handled.

void applicationIdle_StartedAsync(object sender, EventArgs e)
    BeginInvoke(new MethodInvoker(
        delegate() { applicationIdle_Started(sender, e); })
void applicationIdle_Started(object sender, EventArgs e)
    // do stuff here

(For more information see my Events Made Simple article.)

When a message is received, we only need to respond to key and mouse messages. The ones we are interested in are defined in an enum ActivityMessages. All we need to do is check if the message is defined and react accordingly. Regardless of the message, we return false to indicate that we aren't actually processing the message.

bool IMessageFilter.PreFilterMessage(ref Message m)
    if (Enum.IsDefined(typeof(ActivityMessages), m.Msg))
        _TimeRemaining = _IdleTime;
        _TimeElapsed = ZeroTime;
        ActivityEventArgs e = new ActivityEventArgs((ActivityMessages)m.Msg);
    return false;

Every time the internal timer ticks, we decrease the time remaining and check if it's zero. If it is, we raise the idle events and stop the component.

private void timer_Tick(object sender, EventArgs e)
    _TimeElapsed = _TimeElapsed.Add(_TickInterval);
    _TimeRemaining = _TimeRemaining.Subtract(_TickInterval);
    // ...
    if (_TimeRemaining == ZeroTime)

When we stop the component, we need to stop the timer, reset some properties, and unregister from the application messages.

public void Stop()
    if (_IsRunning)
        _TimeRemaining = ZeroTime;
        _TimeElapsed = ZeroTime;
        _IsRunning = false;
        _IsPaused = false;

The Demo

I have included a simple demonstration application to show the component in use. Use the menu or F12 to 'Log In'. Moving/clicking the mouse or pressing a key within the application will reset the counters. Leave it idle until Remaining reads 00:00:00 and you will be automatically logged out.


That's an overview of the basics and is probably all that you will need. The next section gives an outline of all properties, events and methods of all the classes involved.

Application Idle Project Documentation

The project is a class library of the following five files. This is part of a larger component library. It builds down to Winforms.Components.dll and the component resides in the Winforms.Components namespace. Other related classes reside in the Winforms.Components.ApplicationIdleData namespace.


The WinForms component that determines whether an application has received any defined ActivityMessages for a specified TimeSpan.


Designer Visible Properties

  • IdleTime

  • A TimeSpan after which the application should be considered idle if no defined ActivityMessages are received.
  • TickInterval

  • The TimeSpan at which the component 'ticks'. Idleness is checked and appropriate events are raised on each tick.
  • WarnSetting

  • The WarnSettings value used to control warning events generation.
  • WarnTime

  • A TimeSpan at which warning events will be generated depending on the WarnSetting.

Additional Editor Visible Properties (readonly)

  • IsPaused

  • Indicates whether the component is currently paused.
  • IsRunning

  • Indicates whether the component is currently running.
  • TimeElapsed

  • A TimeSpan representing the time since the last activity was detected.
  • TimeRemaining

  • A TimeSpan representing the time until Idle assuming no activity is detected.


Property Changed Events

All the property changed events are raised when the corresponding property changes.

  • IdleTimeChanged
  • TickIntervalChanged
  • WarnSettingChanged
  • WarnTimeChanged

Synchronous Behavior Events

All the synchronous events listed below also have an asynchronous counterpart.

  • Activity

  • Raised when the component detects an activity that is defined in ActivityMessages.
  • Idle [default]

  • Raised when the IdleTime is reached.
  • Paused

  • Raised when the component is paused.
  • Started

  • Raised when the component is started.
  • Stopped

  • Raised when the component is stopped.
  • Tick

  • Raised when the component 'ticks'.
  • UnPaused

  • Raised when the component is unpaused.
  • Warn

  • May be raised when the WarnTime is reached and on each subsequent Tick depending on the WarnSetting.

Asynchronous Behavior Events

For descriptions of these events see the Synchronous Behavior Events section above.


None of the methods take any parameters.

  • GetVersion

  • Gets the assembly version of the component.
  • Restart

  • Stops, and then starts the component.
  • Start

  • Starts the component.
  • Stop

  • Stops the component.
  • TogglePause

  • Toggles the pause state of the component.


Setting IdleTime forces recalculation of TickInterval and WarnTime.
Events are fired only if the associated property changes in the following order.

  1. IdleTimeChanged
  2. TickIntervalChanged
  3. WarnTimeChanged

Setting TickInterval forces recalculation of WarnTime.
Events are fired only if the associated property changes in the following order:

  1. TickIntervalChanged
  2. WarnTimeChanged

TickInterval is forced to be a factor of the IdleTime.
WarnTime is forced to be a multiple of TickInterval and a factor of IdleTime.

IdleTime and TickInterval can only be set when the component isn't running.
Stop, Restart and TogglePause have no effect if the component isn't running.

When the component 'ticks' several events are possible. They are fired in the following order as appropriate.

  1. Tick
  2. Warn
  3. Idle
  4. Stop

All asynchronous events are fired immediately before their synchronous counterparts.


This is a simple enum of Windows messages (sourced from the winuser.h header file) that we're interested in.


This class derives from System.EventArgs and has the following property. It is used in the Activity and ActivityAsync events.

  • ActivityMessage

  • An ActivityMessages member indicating the activity that was detected.


This class derives from System.EventArgs and has the following property. It is used in the Tick and TickAsync events.


An enum used for the WarnSetting property.

  • Tick

  • Warning events are raised when the WarnTime is reached and on each subsequent Tick.
  • Once

  • Warning events are raised only when the WarnTime is reached.
  • Off

  • Warning events are not raised.


  • 22 October 2008: Initial version
  • 01 March 2009: Version 2


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

CEO Dave Meadowcroft
United Kingdom United Kingdom
No Biography provided

You may also be interested in...

Comments and Discussions

QuestionFormulario heredado Pin
Juan Rodriguez15-Aug-15 6:04
memberJuan Rodriguez15-Aug-15 6:04 
AnswerRe: Formulario heredado Pin
DaveyM6924-Aug-15 6:05
mentorDaveyM6924-Aug-15 6:05 
QuestionAuto Log out feature Pin
sanjoygr812-Mar-15 20:39
membersanjoygr812-Mar-15 20:39 
GeneralUseful module Pin
wbanko17-Dec-14 10:28
memberwbanko17-Dec-14 10:28 
GeneralExactly the component I needed. Pin
ZeedijkMike20-Sep-14 10:00
memberZeedijkMike20-Sep-14 10:00 
QuestionHow can I use this in a VB.Net App? Pin
rsmldmv17-Sep-14 9:50
memberrsmldmv17-Sep-14 9:50 
AnswerRe: How can I use this in a VB.Net App? Pin
DaveyM6922-Sep-14 4:07
mentorDaveyM6922-Sep-14 4:07 
QuestionWindows Explorer Crashes Pin
RHBrooks19-May-14 4:47
memberRHBrooks19-May-14 4:47 
AnswerRe: Windows Explorer Crashes Pin
DaveyM6926-May-14 4:38
mentorDaveyM6926-May-14 4:38 
QuestionGood work. Pin
clintoaug31-Mar-14 23:57
memberclintoaug31-Mar-14 23:57 
AnswerRe: Good work. Pin
DaveyM692-Apr-14 10:34
mentorDaveyM692-Apr-14 10:34 
GeneralRe: Good work. Pin
clintoaug2-Apr-14 21:12
memberclintoaug2-Apr-14 21:12 
GeneralRe: Good work. Pin
DaveyM693-Apr-14 11:18
mentorDaveyM693-Apr-14 11:18 
GeneralRe: Good work. Pin
clintoaug9-Apr-14 23:34
memberclintoaug9-Apr-14 23:34 
QuestionReally Cool!!!!! Pin
Nanda Rengasamy29-Oct-13 20:57
memberNanda Rengasamy29-Oct-13 20:57 
QuestionExcellent article. Pin
muralikrishnagangineni15-Mar-13 6:31
membermuralikrishnagangineni15-Mar-13 6:31 
GeneralMy vote of 5 Pin
Bkins6-Jul-12 14:02
memberBkins6-Jul-12 14:02 
GeneralRe: My vote of 5 Pin
DaveyM6910-Jul-12 12:34
mentorDaveyM6910-Jul-12 12:34 
QuestionApplication Idle Pin
habay4lordcom18-Jun-12 5:15
memberhabay4lordcom18-Jun-12 5:15 
AnswerRe: Application Idle Pin
DaveyM6919-Jun-12 9:54
mentorDaveyM6919-Jun-12 9:54 
GeneralRe: Application Idle Pin
habay4lordcom19-Jun-12 23:59
memberhabay4lordcom19-Jun-12 23:59 
GeneralMy vote of 5 Pin
magic.on9-Jun-12 10:12
membermagic.on9-Jun-12 10:12 
GeneralRe: My vote of 5 Pin
DaveyM6919-Jun-12 9:56
mentorDaveyM6919-Jun-12 9:56 
QuestionEvents rised during PAUSED period... Pin
Hurty22-Nov-11 23:30
memberHurty22-Nov-11 23:30 
Hi there! Great job.
I found a bit problem using it though.
I have to create a form after 30 minutes of idling time to show a warning form.
But when I create it, the timer is restarted.
Also tried to pause it , create form and resume it - but it catches the activity even when is paused.
Any help considering the problem... ?

P.S. Also I found that the timer is not working on other threads otherthen the main thread (respectively it was started on). Any chance for property like (GlobalWokring =true/false) that makes it works on all threads/current thread?

modified 23-Nov-11 4:49am.

AnswerRe: Events rised during PAUSED period... Pin
DaveyM6926-Nov-11 1:49
mentorDaveyM6926-Nov-11 1:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.151126.1 | Last Updated 2 Mar 2009
Article Copyright 2008 by DaveyM69
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid