Detecting Application Idle

Detecting if your application has been idle (i.e. no user mouse or keyboard actions) for a certain period of time is straightforward using an IMessageFilter implementation.  The filter would look like this:


using System;

using System.Collections.Generic;
using System.Text;
using OpenNETCF.Win32;
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;

namespace MessageFilterSample
{
  public class InactivityFilter : IMessageFilter
  {
    public event MethodInvoker InactivityElapsed;

    private Timer m_inactivityTimer;

    public InactivityFilter(int timeoutMilliseconds)
    {
      m_inactivityTimer = new Timer();
      m_inactivityTimer.Interval = timeoutMilliseconds;

      m_inactivityTimer.Tick += new EventHandler(m_inactivityTimer_Tick);
      Reset();
    }

    void m_inactivityTimer_Tick(object sender, EventArgs e)
    {
      m_inactivityTimer.Enabled = false;
      Elapsed = true;

      if (InactivityElapsed != null) InactivityElapsed();
    }

    public bool PreFilterMessage(ref Microsoft.WindowsCE.Forms.Message m)
    {
      switch ((WM)m.Msg)
      {
        case WM.KEYUP:
        case WM.LBUTTONUP:
        case WM.MOUSEMOVE:
          // reset the timer
          m_inactivityTimer.Enabled = false;
          m_inactivityTimer.Enabled = true;
          break;
      }
      return false;
    }

    public int Timeout { get; set; }
    public bool Elapsed { get; private set; }

    public void Reset()
    {
      Elapsed = false;
      m_inactivityTimer.Enabled = true;
    }
  }
}


To use it, you must use one of the Run overloads in Application2 to start your application, then you can add your filter like this:


InactivityFilter m_filter = new InactivityFilter(5000);
m_filter.InactivityElapsed += new MethodInvoker(m_filter_InactivityElapsed);
Application2.AddMessageFilter(m_filter);

void m_filter_InactivityElapsed()
{
   MessageBox.Show(“Inactivity timer fired”);
}


Download the sample here:
 

MessageFilterSample.zip (3.92 KB)

10 Comments

  1. Hi,
    Thanks for the sharing. I have a similar solution used for the automatic user logout after elapsed specified interval of the inactivity. Indeed my solution doesn’t require IMessageFilter.

    Article (sorry, only in czech language} with code.
    http://tinyurl.com/q2zhoy

    Google translation (automatic translation is cause of some errors in the code listings, for the correct code refer please to my original spot mentioned above}

    http://tinyurl.com/ocyvh3

  2. Hey Chris,

    I’ve implemented your solution, but I keep getting this compiler error that I can’t explain:

    Error 19 genasm.exe(1) : error There was an error initializing . Method ‘PreFilterMessage’ in type ‘MessageFilterSample.InactivityFilter’ from assembly ‘myDLL, Version=1.0.3436.17996, Culture=neutral, PublicKeyToken=null’ does not have an implementation.

    I’ve implemented that function (copied your code exactly just to make sure), but I keep getting this error. Is there some sort of issue with my version OpenNetCF (OpenNETCF.Windows.Forms.dll 2.3.0.0)?

    Thanks,
    -Aaron

  3. Ouch, this does not work for "sub" forms. For example if I do Application2.Run on my Login form an then Login calls ShowDialog on Form called "Main" which then calls ShowDialog on another form (EnterContact) then only Login has the messages caputred.

    Main and EnterContact do not reset the idle timer.

  4. I figured the "sub" forms out.

    If you change the call from Main.ShowDialog() and EnterContact.ShowDialog() to Application2.ShowDialog(Main, false) and Appliation2.ShowDialog(EnterContact, false) then you will get the correct functionality.

Leave a Reply