如何检测Winforms应用程序已闲置一定时间 [英] How to detect a Winforms app has been idle for certain amount of time

查看:107
本文介绍了如何检测Winforms应用程序已闲置一定时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

What is the best way, to detect if a C# Winforms application has been idle for a certain period of times?

如果用户决定使用ALT + TAB和在30分钟内使用Microsoft Word或其他工具进行某些工作,而使我们的应用程序不使用,我希望我们的应用程序自行终止。

If a user decides to ALT+TAB and do some work with Microsoft Word or whatever for 30 minutes, leaving our app unused, I want our app to self-terminate.

这是一个类似问题的公认答案:
检查如果某个应用程序空闲了一段时间并锁定了它

This is the accepted answer for a similar question: Check if an application is idle for a time period and lock it

但是,答案与Windows空闲了一段时间有关,不是特定的应用。我希望我们的应用程序在30分钟内没有被使用时终止。

However, the answer is pertinent to Windows being idle for a period of time, not a specific application. I want our application to terminate if it's not been used for say, 30 minutes.

我看了看:

http://www.codeproject.com/Articles/13756/Detecting-应用程序空闲

但是我在评论中看到这不适用于多线程应用程序,而我们的应用程序就是其中之一。 我们的应用程序有一个主窗体,该窗体生成模式窗体和无模式窗体,这些窗体使用Async Await填充网格等。

However I read in the comments that this doesn't work for multi-threaded applications, of which our app is one. Our app has a main form, which spawns modal and modeless forms, which use Async Await to fill grids etc.

然后,我查看了SetWindowsHookEx

Then I looked at SetWindowsHookEx, unsure if that would work.

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

Surely someone has a solution (compatible with .NET 4.5 hopefully ) :)

TIA

推荐答案

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

There are many ways to do it and the answer somewhat depends on what you need to do. You are clear and specific about what you need. The following is something I developed that probably would fit your requirements. What it is doing is using Application.Idle to determine when the application has finished processing messages then it sets a timer and filters (listens to) all messages for the application and if a relevant message (such as mouse or keyboard) is received then it resets the timer. It ignores mouse move since it is possible to move the mouse over the application without using the application. It has been a while since I wrote that so I am not sure of the details but I could figure it out if necessary. Note that this is a console program to make the sample easier to try but the code is intended for a forms application.

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

这篇关于如何检测Winforms应用程序已闲置一定时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆