How to detect inactive user
Asked Answered
G

4

35

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.

Gynophore answered 6/2, 2010 at 10:37 Comment(5)
John'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!Halfhardy
@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. :)Cenotaph
@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.Gynophore
What 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.Cenotaph
@LightnessRacesinOrbit: This is not regular desktop environment.Gynophore
M
53

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;

http://delphi.about.com/od/adptips2004/a/bltip1104_4.htm

Marable answered 6/2, 2010 at 10:55 Comment(1)
Note: this API is system-wide, not application-specific.Puling
C
11

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

Cenotaph answered 6/2, 2010 at 10:45 Comment(0)
B
8

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

Bidet answered 6/2, 2010 at 10:39 Comment(3)
Not ever user uses a screensaver.Marable
Screensaver is disabled in this particular application, so no luck with that.Gynophore
+1, but no need for WH_GETMESSAGE hooks, just hook into the message loop that TApplication implements.Caffey
J
3

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.

Jakob answered 13/4, 2012 at 15:7 Comment(2)
Bullied much, huh? :DEndocrinotherapy
"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.Puling

© 2022 - 2024 — McMap. All rights reserved.