各种程序只能在您一段时间没有使用计算机时才能执行某些操作(例如屏幕保护程序、Google 桌面索引等)。
它们是如何知道何时处于非活动状态的?Windows 中是否有某个函数告诉您它已经处于非活动状态了多长时间,或者您必须使用某种键盘/鼠标挂钩来自行跟踪活动情况?
我正在使用 C#,但对任何确定非活动状态的方法都感兴趣。
编辑:更改答案,提供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 命名空间中。[因链接过期而删除]
我认为键盘和鼠标钩子是最有价值的。下面的类可以被插入,你只需要想出如何处理关于键盘和鼠标更新的信息。
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;我们有一个用于此目的的C++ DLL。