How to detect user is inactive
Posted: Thu Aug 23, 2018 1:21 pm
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?
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;
}
}