如何判断 Windows 何时处于非活动状态
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/203384/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to tell when Windows is inactive
提问by dan gibson
Various programs can do stuff only when you haven't used the computer for a while (eg screensaver, Google Desktop indexing, etc).
各种程序只有在您有一段时间没有使用计算机时才能执行某些操作(例如屏幕保护程序、Google 桌面索引等)。
How do they know when it has been inactive? Is there some function in Windows that tells you how long it has been inactive, or do you have to use some kind of keyboard/mouse hook to track activity yourself?
他们如何知道它何时处于非活动状态?Windows 中是否有一些功能可以告诉您它已处于非活动状态的时间,或者您是否必须使用某种键盘/鼠标挂钩来自己跟踪活动?
I'm using C#, but I'm interested in any method of determining the inactivity.
我正在使用 C#,但我对确定不活动的任何方法感兴趣。
回答by TheSoftwareJedi
EDIT: changed answer, providing text and detail behind Shy's answer (which should be and was accepted). Feel free to merge and delete this one.
编辑:更改答案,提供害羞的答案背后的文字和细节(应该并被接受)。随意合并和删除这个。
GetLastInputInfoFunction The GetLastInputInfo function retrieves the time of the last input event.
GetLastInputInfo函数 GetLastInputInfo 函数检索上次输入事件的时间。
Pasted here from P/Invoke
从 P/Invoke 粘贴到这里
This function retrieves the time since last user input
此函数检索自上次用户输入以来的时间
[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:
I implemented a global keyboard and mouse hook during AnAppADay. See this app for the source - it's pretty close to what you want. The classes you'll want are in the AnAppADay.Utils namespace.
[scratched due to linkrot]
FWIW:我在 AnAppADay 期间实现了全局键盘和鼠标挂钩。请参阅此应用程序以获取源代码 - 它非常接近您想要的内容。您需要的类位于 AnAppADay.Utils 命名空间中。
[因链接腐烂而刮伤]
回答by shoosh
回答by Bill
The keyboard and mouse hooks are what I find to be most valuable. The class below can be inserted and you just have to figure out what you want to do with the information about key and mouse updates.
键盘和鼠标挂钩是我认为最有价值的东西。可以插入下面的类,你只需要弄清楚你想用关于键和鼠标更新的信息做什么。
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 );
}
}
}
Of course this only works within the application you are hooking. If you need to track inactivity across the entire system, you need to create a DLL that can be loaded into the address spaces of all other windows. Unfortunately, I haven't heard of any hack that would allow a .net compiled .dll that will work in this scenario; we have a C++ DLL that hooks for this purpose.
当然,这只适用于您正在挂钩的应用程序。如果您需要跟踪整个系统的不活动状态,您需要创建一个可以加载到所有其他窗口地址空间的 DLL。不幸的是,我还没有听说过任何允许 .net 编译的 .dll 在这种情况下工作的黑客;我们有一个用于此目的的 C++ DLL。