How to detect user is inactive

Discussion of application development using iX Developer, including but not limited to getting started, using the functions tab, properties, objects and installation.
Post Reply
LogicG8
Posts: 1
Joined: Wed Aug 22, 2018 2:13 pm

How to detect user is inactive

Post by LogicG8 »

I am attempting to change screens based on system state and whether a user has interacted with the display within a period of time. I have not found a way to detect user inactivity.

I am using a T7A and have tried using GetLastInputInfo and SetWindowsHookEx P/Invokes without success (code below).

The GetLastInputInfo implementation works on my PC when user32.dll is specified and crashes on the T7A. The delegate does not get run when the touch screen is touched with the SetWindowsHookEx attempt.

Have I done something wrong with either implementation or is there an alternate method, maybe hooking into power management or getting an event when the "Automatically turn off backlight" feature activates that can be used instead?

Code: Select all

	public partial class ScreenSaver
	{
		public delegate IntPtr HookProc(int code, IntPtr wParam, IntPtr lParam);
	
		private const int WH_MOUSE_LL = 14;
		private const UInt32 activity_timeout = 10 * 60 * 1000; // 10 minutes

		private static System.Threading.Timer idle = null;
		private static HookProc hookDelegate;
		private static IntPtr hookId = IntPtr.Zero;
		private static UInt32 timestamp = 0;

		// Poll activity and show screensaver screen when idle
		private static void enter(Object state)
		{
			UInt32 dt = (UInt32)Environment.TickCount - timestamp;
			if (dt >= system_timeout) {
				// Show screensaver
			}
		}

		public void leave()
		{
			// Stop showing screensaver
		}

		// Setup timer and hook to monitor user activity
		void ScreenSaver_Created(System.Object sender, System.EventArgs e)
		{
			hookDelegate = new HookProc(HookProcedure);
			hookId = SetWindowsHookEx(WH_MOUSE_LL, hookDelegate, IntPtr.Zero, 0);
			idle = new System.Threading.Timer(enter, null, 10000, 10000);
		}

		// Record user activity and pass processing on
		private IntPtr HookProcedure(int code, IntPtr wParam, IntPtr lParam)
		{
			timestamp = (UInt32)Environment.TickCount;
			return CallNextHookEx(hookId, code, wParam, lParam);
		}

		[DllImport("coredll.dll")]
		private static extern IntPtr GetModuleHandle(string mod);
		[DllImport("coredll.dll")]
		private static extern IntPtr SetWindowsHookEx(
			int type, HookProc hookProc, IntPtr hInstance, int m);
		[DllImport("coredll.dll")]
		private static extern IntPtr CallNextHookEx(
			IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
	}

	public partial class ScreenSaver
	{
		private const UInt32 activity_timeout = 10 * 60 * 1000; // 10 minutes

		private static System.Threading.Timer idle = null;

		// Time since the last input time in milliseconds
		private static UInt32 lastTouch()
		{
			UInt32 dt = 0; // Make input time delta zero on failure

			LASTINPUTINFO last = new LASTINPUTINFO();
			last.cbSize = (uint)Marshal.SizeOf(last);
			if (GetLastInputInfo(ref last)) {
				dt = (UInt32)Environment.TickCount - last.dwTime;
			}
	
			return dt;
		}
		
		// Poll activity screensaver screen if idle
		private static void enter(Object state)
		{
			if (lastTouch() >= activity_timeout) {
				// Show screensaver
			}
		}

		public void leave()
		{
			// Stop showing screensaver
		}

		void ScreenSaver_Created(System.Object sender, System.EventArgs e)
		{
			// Check if idle once per 10 seconds starting 10 seconds from now
			idle = new System.Threading.Timer(enter, null, 1000, 1000);
		}

		[DllImport("coredll.dll")]
		private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

		[StructLayout( LayoutKind.Sequential )]
		struct LASTINPUTINFO
		{
			[MarshalAs(UnmanagedType.U4)]
			public uint cbSize;
			[MarshalAs(UnmanagedType.U4)]
			public UInt32 dwTime;
		}
	}

User avatar
Russ C.
Posts: 213
Joined: Thu Nov 16, 2017 3:32 pm
Contact:

Re: How to detect user is inactive

Post by Russ C. »

If you're requiring users to login, there is a setting to do this in the Security -> Settings -> General
user-inactivity.png
user-inactivity.png (34.84 KiB) Viewed 4038 times
This will not switch screens, but if you add the SystemSecond and SystemCurrentLoggedinUser tags you can do a check every second that says if the user == "" (logged out) then show screen X
Best regards,

Russ
(801) 708-6690
Technical Support
Contact Us

Beijer Electronics AB
http://www.beijerelectronics.us

Post Reply