Tracking user's idle time - WPF

If you are an WPF application developer, then you might faced the situation to lock the UI if the user is idle for sometime. I see many example is people uses the "GetLastInputInfo" which is not an idle solution as it gives the last input time stamp of your operating system. That means even if your application is inactive, but someother application is active, the GetLastInputInfo will not work for you. The better thing is (atleast as from my testing), run the background timer and track for the WPF window's KeyDown and MouseMove events. I cooked up a simple code and I am presenting it here. This static class exposes 2 public method Register and UnRegister. Call these methods from your every Winow loaded and unloaded events. The register method registers the KeyDown and MouseMove events. They get the timestamp from the event arguments and assign to the LastActivityTime. You may better catch easily from the below code.


namespace MyWPF_Samples
{
    using System;
    using System.Windows.Threading;
    using System.Windows;

    public static class UserIdleManager
    {
        static DispatcherTimer timer = null;
        static Window currentActiveWindow = null;
        public static int LastActivityTime { get; set; }
        public static int IdleTime
        {
            get { return System.Environment.TickCount - LastActivityTime; }
        }
        public static void Register(Window window)
        {
            if (timer == null)
            {
                timer = new DispatcherTimer(DispatcherPriority.Background);
                timer.Interval = new TimeSpan(5000);
                timer.Tick += new EventHandler(timer_Tick);
            }
            timer.Start();
            LastActivityTime = System.Environment.TickCount;
            currentActiveWindow = window;
            currentActiveWindow.KeyDown += new System.Windows.Input.KeyEventHandler(window_KeyDown);
            currentActiveWindow.MouseMove += new System.Windows.Input.MouseEventHandler(window_MouseMove);
        }
        static void timer_Tick(object sender, EventArgs e)
        {
            if (System.Environment.TickCount - LastActivityTime > 10000)
            {
                LastActivityTime = System.Environment.TickCount;
                MessageBox.Show("User is idle for 1 min");
                if (currentActiveWindow != null && timer != null)
                {
                    currentActiveWindow.Activate();
                    timer.Start();
                }
            }
        }
        public static void UnRegister(Window window)
        {
            if (window != null)
            {
                window.KeyDown -= new System.Windows.Input.KeyEventHandler(window_KeyDown);
                window.MouseMove -= new System.Windows.Input.MouseEventHandler(window_MouseMove);
            }
            if (timer != null)
                timer.Stop();
        }
        static void window_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
        {
            LastActivityTime = e.Timestamp;
        }
        static void window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            LastActivityTime = e.Timestamp;
        }
    }
}

Sample Usage

void Window1_Unloaded(object sender, RoutedEventArgs e)
{
UserIdleManager.UnRegister(this);
}
void Window1_Loaded(object sender, RoutedEventArgs e)
{
UserIdleManager.Register(this);
}

No comments:

Post a Comment