What is the best way, to detect if a C# Winforms application has been idle for a certain period of times?
If a user decides to ALT+TAB and do some work with Microsof
You would need to decide what "idle" means. I assume no mouse or key input received by the application during the required time.
You could add a message filter that will see all application-wide Windows messages. See Application.AddMessageFilter. Check for the message codes for key down and mouse down, and record the last time that they occur, but return false so that all messages are handled as normal by the runtime. Likely codes are:
WM_LBUTTONDOWN = 513
RBUTTONDOWN = 516
WM_KEYDOWN = 256
Then in a separate timer elsewhere check when the last event is more than 30 minutes ago.
There are also potential issues with "terminating" the application. If the application has modal forms open, it sounds as if it might not be in a particularly safe state to kill abruptly.
There are many ways to do it and the answer somewhat depends on what you need to do. You are clear and specific about what you need. The following is something I developed that probably would fit your requirements. What it is doing is using Application.Idle to determine when the application has finished processing messages then it sets a timer and filters (listens to) all messages for the application and if a relevant message (such as mouse or keyboard) is received then it resets the timer. It ignores mouse move since it is possible to move the mouse over the application without using the application. It has been a while since I wrote that so I am not sure of the details but I could figure it out if necessary. Note that this is a console program to make the sample easier to try but the code is intended for a forms application.
using System;
using System.Security.Permissions;
using System.Windows.Forms;
namespace _121414
{
static class Program
{
public static Timer IdleTimer = new Timer();
const int MinuteMicroseconds = 60000;
static Form1 f = null;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
LeaveIdleMessageFilter limf = new LeaveIdleMessageFilter();
Application.AddMessageFilter(limf);
Application.Idle += new EventHandler(Application_Idle);
IdleTimer.Interval = MinuteMicroseconds; // One minute; change as needed
IdleTimer.Tick += TimeDone;
IdleTimer.Start();
f = new Form1();
Application.Run(f);
Application.Idle -= new EventHandler(Application_Idle);
}
static private void Application_Idle(Object sender, EventArgs e)
{
if (!IdleTimer.Enabled) // not yet idling?
IdleTimer.Start();
}
static private void TimeDone(object sender, EventArgs e)
{
IdleTimer.Stop(); // not really necessary
MessageBox.Show("Auto logoff");
f.Close();
}
}
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
public class LeaveIdleMessageFilter : IMessageFilter
{
const int WM_NCLBUTTONDOWN = 0x00A1;
const int WM_NCLBUTTONUP = 0x00A2;
const int WM_NCRBUTTONDOWN = 0x00A4;
const int WM_NCRBUTTONUP = 0x00A5;
const int WM_NCMBUTTONDOWN = 0x00A7;
const int WM_NCMBUTTONUP = 0x00A8;
const int WM_NCXBUTTONDOWN = 0x00AB;
const int WM_NCXBUTTONUP = 0x00AC;
const int WM_KEYDOWN = 0x0100;
const int WM_KEYUP = 0x0101;
const int WM_MOUSEMOVE = 0x0200;
const int WM_LBUTTONDOWN = 0x0201;
const int WM_LBUTTONUP = 0x0202;
const int WM_RBUTTONDOWN = 0x0204;
const int WM_RBUTTONUP = 0x0205;
const int WM_MBUTTONDOWN = 0x0207;
const int WM_MBUTTONUP = 0x0208;
const int WM_XBUTTONDOWN = 0x020B;
const int WM_XBUTTONUP = 0x020C;
// The Messages array must be sorted due to use of Array.BinarySearch
static int[] Messages = new int[] {WM_NCLBUTTONDOWN,
WM_NCLBUTTONUP, WM_NCRBUTTONDOWN, WM_NCRBUTTONUP, WM_NCMBUTTONDOWN,
WM_NCMBUTTONUP, WM_NCXBUTTONDOWN, WM_NCXBUTTONUP, WM_KEYDOWN, WM_KEYUP,
WM_LBUTTONDOWN, WM_LBUTTONUP, WM_RBUTTONDOWN, WM_RBUTTONUP,
WM_MBUTTONDOWN, WM_MBUTTONUP, WM_XBUTTONDOWN, WM_XBUTTONUP};
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE) // mouse move is high volume
return false;
if (!Program.IdleTimer.Enabled) // idling?
return false; // No
if (Array.BinarySearch(Messages, m.Msg) >= 0)
Program.IdleTimer.Stop();
return false;
}
}
}