如何判断Windows何时处于非活动状态

时间:2008-10-15 01:04:15

标签: .net windows

各种程序只有在您暂时不使用计算机时才能执行操作(例如屏幕保护程序,Google桌面索引等)。

他们如何知道何时无效? Windows中是否有一些功能可以告诉您它处于非活动状态的时间,或者您是否必须使用某种键盘/鼠标钩来自行跟踪活动?

我正在使用C#,但我对确定不活动的任何方法感兴趣。

3 个答案:

答案 0 :(得分:11)

编辑:改变了答案,提供了Shy答案背后的文字和细节(应该被接受)。随意合并并删除这个。

GetLastInputInfo功能 GetLastInputInfo函数检索上次输入事件的时间。

从P / Invoke粘贴到此处

此函数检索自上次用户输入以来的时间

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

static int GetLastInputTime()
{
    int idleTime = 0;
    LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
    lastInputInfo.cbSize = Marshal.SizeOf( lastInputInfo );
    lastInputInfo.dwTime = 0;

    int envTicks = Environment.TickCount;

    if( GetLastInputInfo( ref lastInputInfo ) )
    {
    int lastInputTick = lastInputInfo.dwTime;

    idleTime = envTicks - lastInputTick;
    }

    return (( idleTime > 0 ) ? ( idleTime / 1000 ) : idleTime );
}

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

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

<击> FWIW: 我在AnAppADay期间实现了全局键盘和鼠标钩子。看到这个应用程序的来源 - 它非常接近你想要的。您需要的类位于AnAppADay.Utils命名空间中。 [由于linkrot划伤]

答案 1 :(得分:5)

Google is your friend

基本上使用this.
在使用之前不要忘记完全准备好文档。

答案 2 :(得分:0)

键盘和鼠标挂钩是我认为最有价值的。可以插入下面的类,您只需要弄清楚要对键和鼠标更新的信息做什么。

using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;

namespace Example {

    public class Hook {

        delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

        [FlagsAttribute]
            public enum WindowMessage {
            WM_KEYDOWN =        0x0000000000000100, // &H100
            WM_MOUSEMOVE =      0x0000000000000200, // &H200
            WM_LBUTTONDOWN =    0x0000000000000201, // &H201
            WM_RBUTTONDOWN =    0x0000000000000204,  // &H204
            WH_KEYBOARD = 2,
            WH_MOUSE = 7,
            HC_ACTION = 0
        }

        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        private static extern bool UnhookWindowsHookEx(int idHook);

        [DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
        private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

        //Declare MouseHookProcedure as a HookProc type.
        static HookProc MouseHookProcedure;
        static HookProc KeyboardHookProcedure;

        private static int  mhMouseHook = 0;
        private static int  mhKeyboardHook = 0;

        public Hook() {}

        public static void Init() {
            MouseHookProcedure = new HookProc( MouseHookProc );
            KeyboardHookProcedure = new HookProc( KeyboardHookProc );
            mhMouseHook = SetWindowsHookEx( (int)WindowMessage.WH_MOUSE, MouseHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId() );
            mhKeyboardHook = SetWindowsHookEx( (int)WindowMessage.WH_KEYBOARD, KeyboardHookProcedure, (IntPtr)0, AppDomain.GetCurrentThreadId() );
        }

        public static void Terminate() {
            UnhookWindowsHookEx( mhMouseHook );
            UnhookWindowsHookEx( mhKeyboardHook );
        }

        private static int MouseHookProc( int nCode, IntPtr wParam, IntPtr lParam ) {
            if ( nCode >= 0 ) {
                //do something here to update the last activity point, i.e. a keystroke was detected so reset our idle timer.
            }
            return CallNextHookEx( mhMouseHook, nCode, wParam, lParam );
        }

        private static int KeyboardHookProc( int nCode, IntPtr wParam, IntPtr lParam ) {
            if ( nCode >= 0 ) {
                //do something here to update the last activity point, i.e. a mouse action was detected so reset our idle timer.
            }
            return CallNextHookEx( mhKeyboardHook, nCode, wParam, lParam );
        }

    }
}

当然这仅适用于您正在挂钩的应用程序。如果需要跟踪整个系统的不活动,则需要创建一个可以加载到所有其他窗口的地址空间中的DLL。不幸的是,我没有听说任何允许.net编译.dll的hack将在这种情况下工作;我们有一个为此目的挂钩的C ++ DLL。