<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>&#60;jco-blog&#047;&#62; &#187; C#</title>
	<atom:link href="http://www.elementalp.com/blog/index.php/tag/c/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.elementalp.com/blog</link>
	<description>Software Development Project Notes</description>
	<lastBuildDate>Tue, 05 Jan 2016 18:59:50 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
	<item>
		<title>Windows Forms Inactivity Timeout Class</title>
		<link>http://www.elementalp.com/blog/index.php/2015/05/26/windows-forms-inactivity-timeout-class/</link>
		<comments>http://www.elementalp.com/blog/index.php/2015/05/26/windows-forms-inactivity-timeout-class/#comments</comments>
		<pubDate>Tue, 26 May 2015 21:30:16 +0000</pubDate>
		<dc:creator><![CDATA[ЈЦЅГЇП €ΘΘΚ]]></dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://www.elementalp.com/blog/?p=135</guid>
		<description><![CDATA[[crayon-6a07061487b5f471779891/] [crayon-6a07061487bc2039142435/]]]></description>
				<content:encoded><![CDATA[<p></p><pre class="crayon-plain-tag">originally posted 2013-8-29</pre><p><a href="http://www.elementalp.com/blog/wp-content/uploads/2015/05/WinFormInactivity.png"><img class="alignnone size-full wp-image-136" src="http://www.elementalp.com/blog/wp-content/uploads/2015/05/WinFormInactivity.png" alt="WinFormInactivity" width="598" height="526" /></a></p><pre class="crayon-plain-tag">using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace NPT.Common
{
    /// &amp;amp;lt;summary&amp;amp;gt;
    /// Polls the system periodically and raises the IsIdle event if the
    /// user interface has been idle for at least the specfied number of seconds.
    /// Stops polling once the IsIdle is fired, use Start() to resume polling.
    /// &amp;amp;lt;/summary&amp;amp;gt;
    public class IdleTimer : IDisposable
    {
        [DllImport(&quot;user32.dll&quot;)]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        internal struct LASTINPUTINFO
        {
            public Int32 cbSize;
            public Int32 dwTime;
        }

        private int timeoutSeconds = 0;
        private int pollSeconds = 0;
        private System.Timers.Timer timer = null;
        private System.ComponentModel.ISynchronizeInvoke sychronizingObject = null;

        //ctor
        public IdleTimer(int idleTimeoutSeconds, System.ComponentModel.ISynchronizeInvoke sychronizingObject = null)
        {
            if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Created&quot;);
            pollSeconds = 5;
            if (idleTimeoutSeconds &amp;amp;lt; 5) 
            {
                idleTimeoutSeconds = 5;
                pollSeconds = 4;
            }
            this.timeoutSeconds = idleTimeoutSeconds;
            this.sychronizingObject = sychronizingObject;

        public void Start()
        {
            System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Started&quot;);
            StartPolling();
        }

        public void Stop()
        {
            System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Stopped&quot;);
            StopPolling();
        }

        //event
        public delegate void IsIdleEventHandler(object sender, IdleTimerEventArgs e);
        public event IsIdleEventHandler IsIdle;
        protected virtual void OnIsIdle(IdleTimerEventArgs e)
        {
            //raise event
            StopPolling();
            if (IsIdle != null) IsIdle(this, e);
        }

        //start polling idle time
        private void StartPolling()
        {
            if (timer == null)
            {
                timer = new System.Timers.Timer(pollSeconds * 1000);
                timer.Elapsed += new System.Timers.ElapsedEventHandler(Poll);
                if (sychronizingObject != null) timer.SynchronizingObject = sychronizingObject;
            }
            timer.Start();
        }

        //stop polling idle time
        private void StopPolling()
        {
            if (timer != null) timer.Stop();
        }

        //poll idle time
        private void Poll(object sender, System.Timers.ElapsedEventArgs e)
        {
            StopPolling();
            int idleSeconds = GetIdleTime();
            if (idleSeconds &amp;amp;gt;= timeoutSeconds)
            {
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Idle - Timeout = {1} seconds, Idle time = {0} seconds&quot;, idleSeconds, timeoutSeconds);
                }

                //system has been idle for at least timeoutSeconds seconds
                OnIsIdle(new IdleTimerEventArgs(idleSeconds:idleSeconds,timeoutSeconds:timeoutSeconds)); 
            }
            StartPolling();
        }

        /// &amp;amp;lt;summary&amp;amp;gt;
        /// Returns system idle time in seconds
        /// &amp;amp;lt;/summary&amp;amp;gt;
        /// &amp;amp;lt;returns&amp;amp;gt;&amp;amp;lt;/returns&amp;amp;gt;
        public int GetIdleTime()
        {
            int systemUptime = Environment.TickCount;
            int lastInputTicks = 0;
            int idleTicks = 0;

            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = (Int32)Marshal.SizeOf(lastInputInfo);
            lastInputInfo.dwTime = 0;

            if (GetLastInputInfo(ref lastInputInfo))
            {
                lastInputTicks = (int)lastInputInfo.dwTime;
                idleTicks = systemUptime - lastInputTicks;
            }
            Int32 seconds = idleTicks / 1000;
            return seconds;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposing)
            {
                StopPolling();
                timer = null;
                sychronizingObject = null;
                if (System.Diagnostics.Debugger.IsAttached)
                {
                    System.Diagnostics.Debug.WriteLine(&quot;IdleTimer: Disposed&quot;);
                }
            }
        }
    }

    public class IdleTimerEventArgs : EventArgs
    {
        public IdleTimerEventArgs(int idleSeconds, int timeoutSeconds)
        {
            IdleSeconds = idleSeconds;
            TimeoutSeconds = timeoutSeconds;
        }

        public int IdleSeconds { get; set; }
        public int TimeoutSeconds {get; set;}
    }
}

using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using System.Threading;

//obsolete: [assembly: SecurityPermission(SecurityAction.RequestMinimum, UnmanagedCode = true)]
namespace System.Windows.Forms
{
    public class MessageBoxEx
    {
        public static DialogResult Show(string text, uint timeoutSeconds)
        {
            Setup(&quot;&quot;, timeoutSeconds);
            return MessageBox.Show(text);
        }

        public static DialogResult Show(string text, string caption, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons, icon);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons, icon, defButton);
        }

        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(text, caption, buttons, icon, defButton, options);
        }

        public static DialogResult Show(IWin32Window owner, string text, uint timeoutSeconds)
        {
            Setup(&quot;&quot;, timeoutSeconds);
            return MessageBox.Show(owner, text);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons, icon);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons, icon, defButton);
        }

        public static DialogResult Show(IWin32Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defButton, MessageBoxOptions options, uint timeoutSeconds)
        {
            Setup(caption, timeoutSeconds);
            return MessageBox.Show(owner, text, caption, buttons, icon, defButton, options);
        }

        public delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);
        public delegate void TimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime);

        public const int WH_CALLWNDPROCRET = 12;
        public const int WM_DESTROY = 0x0002;
        public const int WM_INITDIALOG = 0x0110;
        public const int WM_TIMER = 0x0113;
        public const int WM_USER = 0x400;
        public const int DM_GETDEFID = WM_USER + 0;

        [DllImport(&quot;User32.dll&quot;)]
        public static extern UIntPtr SetTimer(IntPtr hWnd, UIntPtr nIDEvent, uint uElapse, TimerProc lpTimerFunc);

        [DllImport(&quot;User32.dll&quot;)]
        public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int UnhookWindowsHookEx(IntPtr idHook);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern IntPtr CallNextHookEx(IntPtr idHook, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int GetWindowTextLength(IntPtr hWnd);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder text, int maxLength);

        [DllImport(&quot;user32.dll&quot;)]
        public static extern int EndDialog(IntPtr hDlg, IntPtr nResult);

        [StructLayout(LayoutKind.Sequential)]
        public struct CWPRETSTRUCT
        {
            public IntPtr lResult;
            public IntPtr lParam;
            public IntPtr wParam;
            public uint message;
            public IntPtr hwnd;
        };

        private const int TimerID = 42;
        private static HookProc hookProc;
        private static TimerProc hookTimer;
        private static uint hooktimeoutSeconds;
        private static string hookCaption;
        private static IntPtr hHook;

        static MessageBoxEx()
        {
            hookProc = new HookProc(MessageBoxHookProc);
            hookTimer = new TimerProc(MessageBoxTimerProc);
            hooktimeoutSeconds = 0;
            hookCaption = null;
            hHook = IntPtr.Zero;
        }

        private static void Setup(string caption, uint timeoutSeconds)
        {
            if (hHook != IntPtr.Zero)
                throw new NotSupportedException(&quot;multiple calls are not supported&quot;);

            hooktimeoutSeconds = timeoutSeconds*1000;
            hookCaption = caption != null ? caption : &quot;&quot;;

            //&quot;AppDomain.GetCurrentThreadId()&quot; is obsolete, however, its replacement &quot;Thread.CurrentThread.ManagedThreadId&quot; isn't correct this context.
            //See: http://stackoverflow.com/questions/772354/appdomain-getcurrentthreadid-vs-thread-managedthreadid-for-windows-api-calls
            #pragma warning disable 618 //disable the obsolete warning
            hHook = SetWindowsHookEx(WH_CALLWNDPROCRET, hookProc, IntPtr.Zero, AppDomain.GetCurrentThreadId()); //obsolete: 
            #pragma warning restore 618 //enable the obsolete warning
        }

        private static IntPtr MessageBoxHookProc(int nCode, IntPtr wParam, IntPtr lParam)
        {
            if (nCode &amp;amp;lt; 0)
                return CallNextHookEx(hHook, nCode, wParam, lParam);

            CWPRETSTRUCT msg = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));
            IntPtr hook = hHook;

            if (hookCaption != null &amp;amp;amp;&amp;amp;amp; msg.message == WM_INITDIALOG)
            {
                int nLength = GetWindowTextLength(msg.hwnd);
                StringBuilder text = new StringBuilder(nLength + 1);

                GetWindowText(msg.hwnd, text, text.Capacity);

                if (hookCaption == text.ToString())
                {
                    hookCaption = null;
                    SetTimer(msg.hwnd, (UIntPtr)TimerID, hooktimeoutSeconds, hookTimer);
                    UnhookWindowsHookEx(hHook);
                    hHook = IntPtr.Zero;
                }
            }

            return CallNextHookEx(hook, nCode, wParam, lParam);
        }

        private static void MessageBoxTimerProc(IntPtr hWnd, uint uMsg, UIntPtr nIDEvent, uint dwTime)
        {
            if (nIDEvent == (UIntPtr)TimerID)
            {
                short dw = (short)SendMessage(hWnd, DM_GETDEFID, IntPtr.Zero, IntPtr.Zero);

                EndDialog(hWnd, (IntPtr)dw);
            }
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPT.Common;

namespace WinFormsIdleTimerTest
{
    public partial class BaseForm : Form
    {
        private IdleTimer idleTimer = null;

        public BaseForm()
        {
            InitializeComponent();
        }

        protected int IdleTimeoutSeconds { get; set; }
        
        protected virtual void StartIdleTimer()
        {
            if (idleTimer == null)
            {
                StopIdleTimer();
                idleTimer = new IdleTimer(idleTimeoutSeconds: IdleTimeoutSeconds, sychronizingObject: this);
                idleTimer.IsIdle += new IdleTimer.IsIdleEventHandler(IdleTimer_IsIdle);
            }
            idleTimer.Start();
        }

        protected virtual void StopIdleTimer()
        {
            if (idleTimer != null) idleTimer.Stop();
        }

        protected virtual void IdleTimer_IsIdle(object sender, IdleTimerEventArgs e)
        {
            //handle IsIdle event, close the form (override in inherting classes to do something different)
            Close();
        }

        public new void Close()
        {
            StopIdleTimer();
            base.Close();
        }

        public new void Hide()
        {
            StopIdleTimer();
            base.Hide();
        }
    }
}

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPT.Common;

namespace WinFormsIdleTimerTest
{
    public partial class MainForm : BaseForm
    {
        public MainForm()
        {
            InitializeComponent();
            IdleTimeoutSeconds = 5;
            StartIdleTimer();
        }

        private void CancelButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        protected override void IdleTimer_IsIdle(object sender, IdleTimerEventArgs e)
        {
            //an optional override of the BaseForm implementation to do something more than just closing the form
            //MessageBoxEx is an implementation of MessageBox that dismisses itself after a specified number of seconds
            var response = MessageBoxEx.Show(
                    &quot;Is there anybody out there?&quot;,
                    string.Format(&quot;System Idle Detected ({0} seconds)&quot;, e.IdleSeconds),
                    MessageBoxButtons.YesNo,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button2,
                    10);
            if (response == System.Windows.Forms.DialogResult.No)
            {

                MessageBoxEx.Show(
                    &quot;\tGoodbye blue sky.&quot;,
                    string.Empty,
                    MessageBoxButtons.OK,
                    MessageBoxIcon.None,
                    MessageBoxDefaultButton.Button1,
                    3);

                Close();
                return;
            }
            StartIdleTimer();
        }
    }
}</pre><p></p>
]]></content:encoded>
			<wfw:commentRss>http://www.elementalp.com/blog/index.php/2015/05/26/windows-forms-inactivity-timeout-class/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
