views:

478

answers:

3

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.

+4  A: 

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

John Knoeller
Not ever user uses a screensaver.
James Campbell
Screensaver is disabled in this particular application, so no luck with that.
Harriv
+1, but no need for `WH_GETMESSAGE` hooks, just hook into the message loop that `TApplication` implements.
mghie
@mghie: thanks, I'm not really up on delphi
John Knoeller
+11  A: 

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

James Campbell