【问题标题】:Check whether user is inactive检查用户是否处于非活动状态
【发布时间】:2012-06-02 07:29:06
【问题描述】:

如何检查用户是否处于非活动状态? 我有这个:

class UserActivity : IMessageFilter
{
    private double afk_time = 0.1;//minutes
    private DateTime last_activity = DateTime.Now;
    public static bool inactive = false;

    private int WM_LBUTTONDOWN = 0x0201;
    private int WM_MBUTTONDOWN = 0x0207;
    private int WM_RBUTTONDOWN = 0x0204;
    private int WM_MOUSEWHEEL = 0x020A;
    private int WM_MOUSEMOVE = 0x0200;
    private int WM_KEYDOWN = 0x0100;

    public bool PreFilterMessage(ref Message m)
    {
        if (m.Msg == WM_LBUTTONDOWN || m.Msg == WM_MBUTTONDOWN || m.Msg == WM_RBUTTONDOWN || m.Msg == WM_MOUSEWHEEL || m.Msg == WM_MOUSEMOVE || m.Msg == WM_KEYDOWN)
        {
            this.last_activity = DateTime.Now;
            inactive = false;
        }

        if (DateTime.Now.AddMinutes(-afk_time) > last_activity)
            inactive = true;

        return false;
    }
}

但我必须在 Program.cs 中运行它

Application.AddMessageFilter(new UserActivity());

我该怎么做才能自行检查用户不活动状态。我会检查一些复选框,它会开始检查。

我想检查全局用户活动 - 在所有系统中,不仅在应用程序中。

我不想不必要地使用 cpu。还是我应该使用其他解决方案?

【问题讨论】:

  • 这个答案/帮助你吗? stackoverflow.com/questions/1421403/…
  • 我看到了这个帖子,但我想检查您链接中的用户不活动是 Application_Idle 事件。我想知道用户不活动多长时间(鼠标和键盘事件)。而且我不知道我使用的解决方案是否正确以及它是否不会使用大量 CPU...

标签: c# .net windows user-inactivity


【解决方案1】:

我已经尝试根据之前的答案构建一个类,我已经对其进行了测试并且它可以正常工作。 它是异步的,但我没有使用异步密钥。如果有人发现一些问题或改进,那么欢迎。

public class User
{
    [StructLayout(LayoutKind.Sequential)]
    public struct LASTINPUTINFO
    {
        public uint cbSize;
        public uint dwTime;
    }

    [DllImport("user32.dll")]
    static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

    public static TimeSpan? GetInactiveTime()
    {
        LASTINPUTINFO info = new LASTINPUTINFO();
        info.cbSize = (uint)Marshal.SizeOf(info);
        if (GetLastInputInfo(ref info))
            return TimeSpan.FromMilliseconds(Environment.TickCount - info.dwTime);
        else
            return null;
    }

    private TimeSpan? LastTime;
    private DispatcherTimer timer = new DispatcherTimer();
    public void RequestUserActivity()
    {
        LastTime = GetInactiveTime();
        timer.Interval = TimeSpan.FromMilliseconds(500);
        timer.Tick += timer_Tick;
        timer.Start();
    }

    void timer_Tick(object sender, EventArgs e)
    {
        TimeSpan? tmpTime = GetInactiveTime();
        if (LastTime.HasValue && tmpTime.HasValue && tmpTime < LastTime)
        {
            timer.Stop();
            UserAtivited(this, new EventArgs());
        }
        else if (!LastTime.HasValue || !tmpTime.HasValue)
        {
            timer.Stop();
            throw new Exception();
        }
    }

    public event EventHandler UserAtivited;
}

现在在您的窗口中创建一个新的 User 实例,注册到 UserActivated 事件并笑 RequestUserActivity()。我的专家会很有帮助。


请不要对我糟糕的英语表示敬意。我说法语。

【讨论】:

    【解决方案2】:

    我发现了这个,而且效果很好! 因此,如果另一个人有问题,这里是解决方案:

        [StructLayout(LayoutKind.Sequential)]
        public struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }
    
        [DllImport("user32.dll")]
        static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
    
    
        public static TimeSpan? GetInactiveTime()
        {
            LASTINPUTINFO info = new LASTINPUTINFO();
            info.cbSize = (uint)Marshal.SizeOf(info);
            if (GetLastInputInfo(ref info))
                return TimeSpan.FromMilliseconds(Environment.TickCount - info.dwTime);
            else
                return null;
        }
    

    【讨论】:

    • 请注意,Environment.TickCount 返回有符号整数,它比 WinApi GetTickCount 中的无符号整数 (DWORD) 更早翻转。也许 GetTickCount 使用起来更安全。因为 LASTINPUTINFO.dwTime 和 GetTickCount 都是 DWORD(无符号整数)。
    猜你喜欢
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-30
    • 2020-01-11
    • 2019-12-10
    • 1970-01-01
    相关资源
    最近更新 更多