How to detect inactive (idle) user in Windows application? I'd like to shutdown application when there hasn't been any input (keyboard, mouse) from user for certain period of time.
-
4John's given you the useful answer. My question is: Why?! If I'm a user and I'm using a program, and I go off for lunch and come back, I'm not a happy camper if it's disappeared. Close resources if you don't want to keep them open or whatever, but don't close the program; let the user know what happened! – T.J. Crowder Feb 06 '10 at 10:45
-
9@T.J. Crowder: While I agree that user feedback is important, it might not be an ordinary office like application or the like. We don't know the nature of the program, or its target audience. It might make sense for this program and for its particular use to close down after a certain amount of idle time. The question is how to detect that idle time, and since there are no indication what kind of program we deal with here, I don't think it's fair to advice against it. :) – Tommy Andersen Feb 06 '10 at 11:10
-
@T.J. Crowder: TommyA is on right track, this is not regular office application or even office environment. Basically I've client applications which are used every now and then (application is always running), and i'd like to remotely update them. It requires application restart but I don't want to interrupt user, so I was planning to wait few minutes if user is doing something. – Harriv Feb 06 '10 at 11:25
-
5What you might wish to do in that particular case, is to, when you notice inactivity, display a box, counting down for 30 seconds or something like that, giving the user a chance to abort the shutdown. – Tommy Andersen Feb 06 '10 at 11:56
-
@LightnessRacesinOrbit: This is not regular desktop environment. – Harriv Apr 29 '14 at 08:14
4 Answers
To track a user's idle time you could hook keyboard and mouse activity. Note, however, that installing a system-wide message hook is a very invasive thing to do and should be avoided if possible, since it will require your hook DLL to be loaded into all processes.
Another solution is to use the GetLastInputInfo
API function (if your application is running on Win2000 (and up) machines).
GetLastInputInfo
retrieves the time (in milliseconds) of the last input event (when the last detected user activity has been received, be it from keyboard or mouse).
Here's a simple example. The SecondsIdle
function returns a number of second with no user activity (called in an OnTimer
event of a TTimer
component).
~~~~~~~~~~~~~~~~~~~~~~~~~
function SecondsIdle: DWord;
var
liInfo: TLastInputInfo;
begin
liInfo.cbSize := SizeOf(TLastInputInfo) ;
GetLastInputInfo(liInfo) ;
Result := (GetTickCount - liInfo.dwTime) DIV 1000;
end;
procedure TForm1.Timer1Timer(Sender: TObject) ;
begin
Caption := Format('System IDLE last %d seconds', [SecondsIdle]) ;
end;

- 6,706
- 3
- 32
- 39

- 5,057
- 2
- 35
- 54
You might want to see the answer to this question: How to tell when Windows is inactive [1] it is basically same question the solution suggested is to use the GetLastInputInfo
[2] API call.
This post explains some aspects as well: (The Code Project) How to check for user inactivity with and without platform invokes in C# [3]
[1] How to tell when Windows is inactive
[2] http://msdn.microsoft.com/en-us/library/ms646302%28VS.85%29.aspx
[3] http://www.codeproject.com/KB/cs/uim.aspx

- 1
- 1

- 7,165
- 1
- 31
- 50
Your application will get a WM_SYSCOMMAND
message with SC_SCREENSAVE
as a command id when the Screen Saver is about to kick in. Would that do? there's also the SC_MONITORPOWER
command id when the monitor is about to blank (also a WM_SYSCOMMAND message).
Edit: looking at the comments, it appears that you don't care about whether the user is inative, but rather whether your application is inactive.
This is easy. If your app is minimized, then the user isn't interacting with it. If your app is not the foreground application, that's a good inicator as well.
You could also pay attention to messages in your pump to notice if there have been any user input messages to your app, In C++ adding code to the pump is trivial, in delphi you can use a WH_GETMESSAGE hook to monitor the pump hook into the message loop that TApplication implements. Or GetLastInputInfo

- 33,512
- 4
- 61
- 92
-
-
Screensaver is disabled in this particular application, so no luck with that. – Harriv Feb 06 '10 at 11:19
-
+1, but no need for `WH_GETMESSAGE` hooks, just hook into the message loop that `TApplication` implements. – mghie Feb 06 '10 at 19:49
This SecondsIdle doens't work at all. The way is to use a TTimer combined with a second variable that resets every time user inputs mouse or keyboard.

- 8,596
- 20
- 79
- 153
-
-
"Doesn't work" means, that the SecondsIdle/GetLastInputInfo returned value is system-wide, not application specific. In respect to that, and the OP question appears to be about Application being idle (not sure of that, anyway), not system being idle, I did +1. – Arnaud Bouchez Dec 09 '19 at 09:37