如何检测Winforms应用程序已空闲一段时间

时间:2016-04-05 15:33:27

标签: c# .net winforms

检测C#Winforms应用程序是否已空闲一段时间的最佳方法是什么?

如果用户决定使用ALT + TAB并使用Microsoft Word或其他任何工作30分钟,我们的应用程序未使用,我希望我们的应用能够自行终止。

这是类似问题的公认答案: Check if an application is idle for a time period and lock it

但是,答案与Windows闲置一段时间相关,特定应用程序。我希望我们的申请终止,如果它没有被用于说,30分钟。

我看了看这个:

http://www.codeproject.com/Articles/13756/Detecting-Application-Idleness

但是我在评论中读到这对多线程应用程序不起作用,我们的应用程序就是其中之一。 我们的应用程序有一个主窗体,它产生模态和无模式窗体,使用Async Await来填充网格等。

然后我查看了SetWindowsHookEx,不确定这是否有用。

当然有人有解决方案(希望与.NET 4.5兼容):)

TIA

2 个答案:

答案 0 :(得分:10)

有很多方法可以做到,答案在某种程度上取决于你需要做什么。您清楚明确地了解自己的需求。以下是我开发的可能符合您要求的内容。它正在做的是使用Application.Idle来确定应用程序何时完成处理消息然后它设置一个计时器并过滤(监听)应用程序的所有消息,如果收到相关消息(如鼠标或键盘),那么它重置计时器。它忽略鼠标移动,因为可以在不使用应用程序的情况下将鼠标移动到应用程序上。我写这篇文章已经有一段时间了,所以我不确定细节,但如果有必要,我可以弄明白。请注意,这是一个控制台程序,可以使示例更容易尝试,但代码适用于表单应用程序。

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;
        }
    }
}

答案 1 :(得分:0)

你需要决定什么&#34;空闲&#34;手段。我假设应用程序在所需的时间内没有收到任何鼠标或键输入。

您可以添加一个消息过滤器,该过滤器将查看所有应用程序范围的Windows消息。见Application.AddMessageFilter。检查按键和鼠标按下的消息代码,并记录上次发生的消息代码,但返回false,以便运行时正常处理所有消息。可能的代码是:

WM_LBUTTONDOWN = 513
RBUTTONDOWN = 516
WM_KEYDOWN = 256

然后在别处的另一个计时器中检查最后一个事件是否超过30分钟。

还有潜在的问题&#34;终止&#34;应用程序。如果应用程序打开了模态窗体,听起来好像它可能没有特别安全的状态突然杀死。