Jump to content


Check out our Community Blogs

Register and join over 40,000 other developers!


Recent Status Updates

View All Updates

Photo
- - - - -

Detect User Idle And Do Something After Some Time Ellapsed, Part 1: Local User Idle Detection

timer

  • Please log in to reply
1 reply to this topic

#1 Luthfi

Luthfi

    CC Leader

  • Expert Member
  • PipPipPipPipPipPipPip
  • 1320 posts
  • Programming Language:PHP, Delphi/Object Pascal, Pascal, Transact-SQL
  • Learning:C, Java, PHP

Posted 03 May 2012 - 05:45 AM

This tutorial is the first part of two parts tutorial of Detect User Idle And Do Something After Some Time Ellapsed tutorials. The second and final part of this tutorial can be found here. The second part explains how to do the user idle detection system wide.


Overview

Sometimes in your application you need to know if the user has been idle for some time. Mostly this is used for improving security. For example, a banking application may want to logging out the current user once it detects that the user has been idle for at least 5 minutes. This prevents other people from using the application with the logged in user privilege in case the real user is away from the computer forgetting to logout first.

There are two kinds of this "user idle" detection. The first one is to detect idly user only for the application, and the other one is to detect if the user is idle system wide. For the first one, the user is considered idle if our application does not detect user activity performed on it. So if the user is busy with other application, our application will still consider that the user is idle. Let's call this kind of detection as "local user idle detection".

For the second one, the user is considered idle if he/she really does not interact with the computer no matter which focused application is. Let's call this detection as "System-wide user idle detection".


Local User Idle Detection

For this we can use TApplicationEvents component usually found in Additional tab of the component pallette. It has OnIdle event, which will be triggered when user stop doing any activity with the application. Combined with TTimer (found in System tab), we can do some action after user has been idle for specified time.

It's quite simple to do that. The basic steps would be:
  • Set the interval of the TTimer to the amount of time we want to wait before executing the action.
  • Set the Enabled property of the TTimer to False.
  • Enable the TTimer in the TApplicationEvents's OnIdle event.
  • Execute the action in the TTimer's OnTimer event.
However you must have noted by now that there is a flaw in the above steps. I.e. we didn't stop the timer when user become active. For example, if you set to do the action after 5 minutes of user inactivity, the action will always be executed, even if the user become active just 1 minute after he/she became idle. Now that would be annoying.

So we need a way to detect that the user is active. After dig a bit deeper to Windows inner working, we found that user activity can be detected by the reception of windows messages. For our case, we can just detect the reception of the following messages.Fortunately for us, TApplicationEvents has OnMessage even that will be triggered everytime any window within the application receive window message. In the even handler there is a Handled parameter of boolean type. If you set this parameter to True the message simply will be dropped, and the original destination window will never receive it.


Demo project

For the demo project, create a new application, drop a TApplicationEvents, a TTimer, a TLabel, and a TButton. Leave their properties to default values, and arrange them to get something like shown below.

LocalUserIdle_Design01.png
  • Click the TApplicationEvents, open the Object Inspector and open its Events tab. Double click in the area labeled OnIdle to create skeleton code of OnIdle event handler. Then use the following code for the event handler.
     
    procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
    begin
      // if the timer has been enabled means the idle duration is already counting.
      // Do not continue to avoid resetting the start idle time
      if Timer1.Enabled then Exit;
    
      // store the time when the user become idle
      FStartIdle := GetTickCount;
    
      // enable the timer
      Timer1.Enabled := True;
    end;
    
     

    Double click on our TTimer to generate skeleton code of its OnTimer event handler. And use the following code for the event handler.
    procedure TForm1.Timer1Timer(Sender: TObject);
    var
      vIdleTime : Cardinal;
      vHours : Cardinal;
      vMinutes : Cardinal;
      vSeconds : Cardinal;
    begin
      // calculate the idle time. It's in milliseconds
      vIdleTime := GetTickCount - FStartIdle;
    
      // get how many hour has the user been idle
      vHours := vIdleTime div (60 * 60 * 1000);
      if vHours > 0 then
        vIdleTime := vIdleTime - (vHours * 60 * 60 * 1000);
    
      // get the minutes part of the time the user been idle
      vMinutes := vIdleTime div (60 * 1000);
      if vMinutes > 0 then
        vIdleTime := vIdleTime - (vMinutes * 60 * 1000);
    
      // get the seconds part of the time the user been idle
      vSeconds := vIdleTime div 1000;
    
    
      // Show the duration of time user has been idle
      Label1.Caption := Format('%.2d:%.2d:%.2d', [vHours, vMinutes, vSeconds]);
    end;
    
    Click the TApplicationEvents, open the Object Inspector and open its Events tab. Double click in the area labeled OnMessage to create skeleton code of OnMessage event handler. Then use the following code for the event handler.
    procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
    var Handled: Boolean);
    begin
      Handled := False;
      case Msg.message of
        WM_KEYDOWN
        , WM_MOUSEMOVE
        , WM_MOUSEWHEEL
        , WM_LBUTTONDOWN
        , WM_RBUTTONDOWN
        , WM_MBUTTONDOWN : Timer1.Enabled := False;
      end;
    end
Upon running, the demo project will look like below (after you have been idle for some time).

LocalUserIdle_Run01.png


Note that if you activate other application and do some activity with it (typing some text, clicking mouse, things like that), the idle counter of our demo application will still counting. The counting however will reset if you move the mouse cursor over our demo application's form, or click on the form or the button.

That's it! Now you can see how easy it is to detect how long has your application user been idle and take action accordingly. You just need to adjust your TTimer's Interval property and what you want to do in its OnTimer event.

Full source code of the demo project is attached. Feel free to use or improve it.

Visit the second part of this tutorial in this page. It discusses how to do "System-wide user idle detection".

Cheers!

Attached Files


Edited by LuthfiHakim, 12 February 2013 - 12:51 AM.

  • 2

#2 Marichele

Marichele

    CC Lurker

  • Just Joined
  • Pip
  • 1 posts

Posted 27 June 2014 - 01:25 PM

Thank you!


  • 0





Also tagged with one or more of these keywords: timer

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download