How to tell when to time-out an application


How can I determine that a user has been inactive for a certain length of time so that I may exit the application?


This is an interesting question because it introduces one form of security for an application, and that is time-sensitive, user activity-based processing. This type of "awareness" in a program can usually be found in dialup programs (CompuServe, MSN), but they also reside in security log-ins, in which if a response is not made within a discrete period of time, the program will close and you'll have to start all over again.

In Delphi, this is pretty easy to implement. What you're about to see is not the prettiest solution in the world, but it works.

Here's how to implement user activity-based time-sensitivity in your programs:

  1. In the main form of your application, set the KeyPreview property to True so the form will see keystrokes before any other components (you'll see why when you see the code for the OnKeyDown method). And in the FormCreate method, write the following code:
    procedure TForm1.FormCreate(Sender: TObject);
    begin
      TimeOut := 0;
    end;
  2. Drop a Timer component on the form and set its interval to 1000 milliseconds (the default).
  3. Switch to the editor. Under the implementation section, declare the following const and var:
    const
      MaxTimeOutValue = 300; {This is 300 seconds, or five minutes}
    var
      TimeOut : Integer; {This will be incremented by the Timer}
    
  4. Write the following procedure and declare in the private section of your form:
    procedure TForm1.ResetTimeOut;
    begin
      TimeOut := 0;
    end;
  5. Open up the OnKeyDown method for your form and put the following code:
    procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    begin
      ResetTimeOut;
    end;

    This calls ResetTheTimer which, in turn, resets the TimeOut variable to zero, then disables and re-enables the Timer. The reason we do form-level processing of the keystrokes is so that no matter which component the user is typing in, keystrokes are always picked up by the form. Otherwise, you'd have to add this code to every component, and if you have a lot on your form ... yikes! I'd rather not think about it

  6. In the OnTimer event of the Timer, put the following code:
procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Inc(TimeOut);
  if TimeOut = MaxTimeOutValue then begin
    Timer1.Enabled := False;
    Close;
  end;
end;

This increments the TimeOut variable and compares it against the MaxTimeOutValue. If TimeOut equals MaxTimeOutValue, the timer is disabled and Close is called.

So how does this all work?

When the user presses a key while the form is running, TimeOut is reset to 0. This means that if the user is constantly typing, there's no way TimeOut can ever reach MaxTimeOutValue. However, once the user stops typing, because the timer is always enabled, TimeOut will be incremented every second, and will eventually reach the value equivalent to MaxTimeOutValue.

This isn't pretty, but it works.