如何在我的C#应用程序中确定空闲时间?

3

“工作正常”是指您在Windows 7中获取到了正确的数据吗? - jheddings
我可以在这里分享Exec,但我认为有些人可能会认为它是病毒等。 - Styler2go
你能运行我的可执行文件吗?你能告诉我是哪个Win8版本吗? - Styler2go
3个回答

9

我对你的方法采取了稍微不同的方法...这决定了应用程序的空闲时间,而不是使用系统范围内的空闲时间。我不确定这是否符合您的需求,但它可能会帮助您进一步。它还具有纯.NET的优点,而不是使用DllImport

public partial class MyForm : Form, IMessageFilter {

    private Timer _timer;

    // we only need one of these methods...
    private DateTime _wentIdle;
    private int _idleTicks;

    public MyForm() {

        // watch for idle events and any message that might break idle
        Application.Idle += new EventHandler(Application_OnIdle);
        Application.AddMessageFilter(this);

        // use a simple timer to watch for the idle state
        _timer = new Timer();
        _timer.Tick += new EventHandler(Timer_Exipred);
        _timer.Interval = 1000;
        _timer.Start();

        InitializeComponent();
    }

    private void Timer_Exipred(object sender, EventArgs e) {
        TimeSpan diff = DateTime.Now - _wentIdle;

        // see if we have been idle longer than our configured value
        if (diff.TotalSeconds >= Settings.Default.IdleTimeout_Sec) {
            _statusLbl.Text = "We Are IDLE! - " + _wentIdle;
        }

        /**  OR  **/

        // see if we have gone idle based on our configured value
        if (++_idleTicks >= Settings.Default.IdleTimeout_Sec) {
            _statusLbl.Text = "We Are IDLE! - " + _idleTicks;
        }
    }

    private void Application_OnIdle(object sender, EventArgs e) {
        // keep track of the last time we went idle
        _wentIdle = DateTime.Now;
    }

    public bool PreFilterMessage(ref Message m) {
        // reset our last idle time if the message was user input
        if (isUserInput(m)) {
            _wentIdle = DateTime.MaxValue;
            _idleTicks = 0;

            _statusLbl.Text = "We Are NOT idle!";
        }

        return false;
    }

    private bool isUserInput(Message m) {
        // look for any message that was the result of user input
        if (m.Msg == 0x200) { return true; } // WM_MOUSEMOVE
        if (m.Msg == 0x020A) { return true; } // WM_MOUSEWHEEL
        if (m.Msg == 0x100) { return true; } // WM_KEYDOWN
        if (m.Msg == 0x101) { return true; } // WM_KEYUP

        // ... etc

        return false;
    }
}

我这里有两种方法来确定闲置... 一种是使用 DateTime 对象,另一种是使用简单的计数器。可能会发现其中一个更适合您的需求。

如果您想考虑作为用户输入的消息列表,请访问此处


1
但我需要用户的真实AFK时间。系统范围内。 - Styler2go

2
    protected override void OnLoad(EventArgs e)
    {
    /* Check if we are in idle mode - No mouse movement for 2 minutes */
    System.Windows.Forms.Timer CheckIdleTimer = new                    System.Windows.Forms.Timer();
    CheckIdleTimer.Interval = 120000;
    CheckIdleTimer.Tick += new EventHandler(CheckIdleTimer_Tick);
    CheckIdleTimer.Start();
    }
    private void CheckIdleTimer_Tick(object sender, EventArgs e)
    {
    uint x = IdleTimeFinder.GetIdleTime();
    if (x > 120000) {
         //...do something
    }
    }


    public class IdleTimeFinder
    {
    [DllImport("User32.dll")]
    private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

    [DllImport("Kernel32.dll")]
    private static extern uint GetLastError();

    public static uint GetIdleTime()
    {
    LASTINPUTINFO lastInPut = new LASTINPUTINFO();
    lastInPut.cbSize     (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
    GetLastInputInfo(ref lastInPut);
    return ((uint)Environment.TickCount - lastInPut.dwTime);
    }

   public static long GetLastInputTime()
   {
    LASTINPUTINFO lastInPut = new LASTINPUTINFO();
    lastInPut.cbSize                (uint)System.Runtime.InteropServices.Marshal.SizeOf(lastInPut);
    if (!GetLastInputInfo(ref lastInPut))
    {
    throw new Exception(GetLastError().ToString());
    }
    return lastInPut.dwTime;
    }
    }


 internal struct LASTINPUTINFO
{
    public uint cbSize;

    public uint dwTime;
}

1
以下是如何在Windows中检测“空闲时间”的示例代码。这里的“空闲时间”是指没有用户与Windows进行交互(例如没有键盘和鼠标输入)的时间。
检测空闲时间用于应用程序,如MSN Messenger,在用户未与Windows进行交互一定时间后将状态更改为“离开”。
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GetLastInput_Demo
{
    /// <summary>
    /// Summary description for Form1.
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(out LASTINPUTINFO plii);

        [StructLayout( LayoutKind.Sequential )]
        struct LASTINPUTINFO
        {
            public static readonly int SizeOf =
                   Marshal.SizeOf(typeof(LASTINPUTINFO));

            [MarshalAs(UnmanagedType.U4)]
            public int cbSize;   
            [MarshalAs(UnmanagedType.U4)]
            public int dwTime;
        }

        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.Timer timer1;
        private System.ComponentModel.IContainer components;

        public Form1()
        {
            //
            // Required for Windows Form Designer support
            //
            InitializeComponent();

        }

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        protected override void Dispose( bool disposing )
        {
            if( disposing )
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose( disposing );
        }
        #region Windows Form Designer generated code
        private void InitializeComponent()
        {
            // Code is omitted here.
        }
        #endregion

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            timer1.Enabled = !timer1.Enabled;
        }

        private void timer1_Tick(object sender, System.EventArgs e)
        {
            int idleTime = 0;
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = Marshal.SizeOf( lastInputInfo );
            lastInputInfo.dwTime = 0;

            int envTicks = Environment.TickCount;

            if( GetLastInputInfo( out lastInputInfo ) )
            {
                int lastInputTick = lastInputInfo.dwTime;
                idleTime = envTicks - lastInputTick;
            }

            int a;
           
            if(idleTime > 0)
               a = idleTime / 1000;
            else
               a = idleTime;

            label1.Text = a.ToString();
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接