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

Sco*_*ott 7 .net c# winforms

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

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

这是类似问题的可接受答案: 检查应用程序是否在一段时间内处于空闲状态并将其锁定

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

我看着这个:

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

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

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

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

TIA

use*_*660 12

有很多方法可以做到这一点,答案在某种程度上取决于你需要做什么.您清楚明确地了解自己的需求.以下是我开发的可能符合您要求的内容.它正在做的是使用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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)