I have an inactivity timer that keeps checking for inactivity throughout the app. The problem is, when message box is open, the timer is not ticking and checking for inactivity as long as the MessageBox stays open. When it is closed, it works fine.
The code used here is taken from: How to detect a Winforms app has been idle for certain amount of time
UIInactivity.cs (Track inactivity)
public class UIInactivity
{
public static Timer IdleTimer;
private readonly int _timeoutDuration;
private InactivityState _inactivityState;
public event Action<InactivityState> NotifyInActivity;
public UIInactivity(int timeoutDurationInMinutes, InactivityState inactivityState)
{
_timeoutDuration = (int)TimeSpan.FromMinutes(timeoutDurationInMinutes).TotalMilliseconds;
_inactivityState = inactivityState;
InitInactivity();
}
private void InitInactivity()
{
//Application.EnableVisualStyles(); //Uncomment this line for new look and feel.
IdleTimer = new Timer();
LeaveIdleMessageFilter limf = new LeaveIdleMessageFilter();
Application.AddMessageFilter(limf);
IdleTimer.Interval = _timeoutDuration;
IdleTimer.Tick += TimeDone;
IdleTimer.Enabled = false;
}
private void Application_Idle(object sender, EventArgs e)
{
if (!IdleTimer.Enabled)
{
IdleTimer.Start();
}
}
private void TimeDone(object sender, EventArgs e)
{
StopTimer();
NotifyInActivity?.Invoke(_inactivityState);
}
public void StopTimer()
{
IdleTimer.Stop();
IdleTimer.Enabled = false;
Application.Idle -= new EventHandler(Application_Idle);
}
public void StartTimer(int minutes)
{
if (IdleTimer != null && !IdleTimer.Enabled)
{
if (minutes > 0)
{
IdleTimer.Interval = (int)TimeSpan.FromMinutes(minutes).TotalMilliseconds;
}
else
{
throw new Exception("Inavlid timeout duration for Activity Logger");
}
IdleTimer.Enabled = true;
IdleTimer.Start();
Application.Idle += new EventHandler(Application_Idle);
}
}
}
[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 (!UIInactivity.IdleTimer.Enabled) // idling?
return false; // No
if (Array.BinarySearch(Messages, m.Msg) >= 0)
UIInactivity.IdleTimer.Stop();
return false;
}
}
Somewhere in the application a form opens a warning messagebox as follows when trying to save changes,
if (DialogResult.Yes == MessageBox.Show(m_ResMngr.GetString("ChanRangeWarn"),m_ResMngr.GetString("Warning"),MessageBoxButtons.YesNo,MessageBoxIcon.Warning))
{
//Something
}
When this MessageBox is open, it's not checking for inactivity. How can I resolve this?
Application.Idleand/orLeaveIdleMessageFilterrelevant for this problem? IsTimeDonenot called, even when the timer is enabled and elapsed? I'm not really sure I understand how the example is supposed to work.