#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2012
    Location
    Bandung, Indonesia
    Posts
    3
    Rep Power
    0

    Program that auto-logout?


    I have a program that requires user to login, but I want the program logout if there's no activity (no mouse/keyboard event) for certain amount of time. How can I do that?
  2. #2
  3. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2012
    Location
    Bandung, Indonesia
    Posts
    3
    Rep Power
    0

    Partially solved


    After searching for hours, I found a clue to the problem, it's called HOOK.

    Since am a new user, the forum rules says I can't tell you the URL where I get the information, but I want to thanks Zarko Gajic in delphi dot about dot com.

    I made a test program just to hook the keyboard, and later will hook the mouse.

    { Unit for all incoming projects}
    unit LocalKeyBoardHook_Unit;

    interface

    uses Windows, SysUtils;

    Type
    TKeyBoardHookFunc = function (code: integer; wParam: word; lParam: longword): longword; stdcall;

    function SetupLocalKeyBoardHook(KeyBoardHookProc: TKeyBoardHookFunc): Boolean;
    function RemoveLocalKeyBoardHook: Boolean;

    Var
    KeyBoardHookHandle: HHook;
    KeyBoardHookInstalled: Boolean;

    implementation

    function SetupLocalKeyBoardHook(KeyBoardHookProc: TKeyBoardHookFunc): Boolean;
    begin
    KeyBoardHookHandle := SetWindowsHookEX(WH_KEYBOARD, @KeyBoardHookProc,0,GetCurrentThreadID());

    Result := KeyBoardHookHandle <> 0
    end;


    function RemoveLocalKeyBoardHook: boolean;
    begin
    If KeyBoardHookInstalled then
    Result := UnHookWindowsHookEx(KeyBoardHookHandle);
    end;

    begin
    KeyBoardHookInstalled := False;
    end.




    { Main Project Unit }
    unit Hook1_Unit;

    interface

    uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, ExtCtrls, StdCtrls, LocalKeyBoardHook_Unit;

    type
    TForm1 = class(TForm)
    Label1: TLabel;
    Button1: TButton;
    Timer1: TTimer;
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);

    private
    { Private declarations }
    TimerPassed: Integer;

    public
    { Public declarations }
    end;

    var
    Form1: TForm1;
    CTimer: Integer;

    implementation

    {$R *.dfm}

    function KeyBoardHookFunction(code: integer; wParam: word; lParam: longword): longword; stdcall;
    begin
    if code < 0 then
    begin
    KeyBoardHookFunction := CallNextHookEx(KeyBoardHookHandle,code,wParam,lparam);
    Exit;
    end;

    // Reset the CTimer variable
    CTimer := 0;

    CallNextHookEx(KeyBoardHookHandle,code,wParam,lparam);

    KeyBoardHookFunction := 0;
    Exit;
    end;

    procedure TForm1.Button1Click(Sender: TObject);
    begin
    Button1.Caption := 'KeyBoard Hook Started';
    CTimer := 0;
    TimerPassed := 0;
    SetupLocalKeyBoardHook(KeyBoardHookFunction);
    Timer1.Enabled := True;
    end;

    procedure TForm1.FormDestroy(Sender: TObject);
    begin
    KeyBoardHookInstalled := Not RemoveLocalKeyBoardHook;
    end;

    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
    Inc(CTimer);

    // if no keyboard is pressed in 5 seconds
    if CTimer > 4 then
    begin
    Inc(TimerPassed);
    Label1.Caption := 'Hooked ' + IntToStr(TimerPassed)
    end;
    end;

    end.



    { MainForm DFM }
    object Form1: TForm1
    Left = 0
    Top = 0
    Caption = 'Form1'
    ClientHeight = 300
    ClientWidth = 635
    Color = clBtnFace
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -11
    Font.Name = 'Tahoma'
    Font.Style = []
    OldCreateOrder = False
    OnDestroy = FormDestroy
    PixelsPerInch = 96
    TextHeight = 13
    object Label1: TLabel
    Left = 112
    Top = 56
    Width = 31
    Height = 13
    Caption = 'Label1'
    end
    object Button1: TButton
    Left = 200
    Top = 51
    Width = 181
    Height = 25
    Caption = 'Start KeyBoard Hook'
    Font.Charset = DEFAULT_CHARSET
    Font.Color = clWindowText
    Font.Height = -13
    Font.Name = 'Tahoma'
    Font.Style = []
    ParentFont = False
    TabOrder = 0
    OnClick = Button1Click
    end
    object Timer1: TTimer
    Enabled = False
    OnTimer = Timer1Timer
    Left = 461
    Top = 48
    end
    end
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    354
    Rep Power
    7
    Originally Posted by meiya777
    I have a program that requires user to login, but I want the program logout if there's no activity (no mouse/keyboard event) for certain amount of time. How can I do that?
    You may also want to look at this, also from About.com

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

    The approach is to track a system idle time. After a specified period of idle time, you can initiate a log out.

    Another option, same idea

    http://www.delphigeist.com/2009/11/how-to-get-system-idle-time.html
    Last edited by majlumbo; April 24th, 2012 at 02:40 PM.
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Apr 2012
    Location
    Bandung, Indonesia
    Posts
    3
    Rep Power
    0
    Thanks for the links, it's very interesting.

    Is there anyway I can track local program idle time, rather than system-wide?

    Tried to goog with no luck.
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2008
    Posts
    354
    Rep Power
    7
    Originally Posted by meiya777
    Thanks for the links, it's very interesting.

    Is there anyway I can track local program idle time, rather than system-wide?

    Tried to goog with no luck.
    There is. You can use Application.OnIdle

    You didn't mention which version of Delphi you are using, so depending on which...

    If you have a TApplicationEvents component under the Additional tab, select it and drop one on your form. Select it, then in the object inspector go to the events tab and double click the OnIdle event. This will add the OnIdle method, for now, just add two slashes '//' between the begin end blocks so Delphi doesn't delete the block before you have a chance to add code.

    If you don't have the component on the palette, then add on your form's object declaration, under "private" an event handler for the application's on idle event.

    Code:
    type
    TForm1 = class(TForm)
       ...
       procedure FormCreate(Sender: TObject);//You'll need to add code to FormCreate method
    private
      procedure ApplicationEvents1Idle(Sender: TObject;var Done: Boolean);//Add this method (name is same as if the component existed - you can pick anything as long as it matches what is used to link it to in FormCreate)
       ...
    public
       ...
    end;
    then you need to connect the event with it's handler, so in your Form's OnCreate method add

    Code:
    procedure TForm1.FormCreate(Sender: TObject);
    begin
       ...
       Application.OnIdle := ApplicationEvents1Idle;//Add this
       ...
    end;
    ***********************
    Now you need to add a TTimer component to your form.
    TTimer is in the System tab.

    Add a integer variable to your private section
    and initialize it to zero in the FormCreate method

    Code:
    type
    TForm1 = class(TForm)
       ...
       procedure FormCreate(Sender: TObject);//You'll need to add code to FormCreate method
    private
      IdleCount: Integer;
      procedure ApplicationEvents1Idle(Sender: TObject;var Done: Boolean);
       ...
    public
       ...
    end;
    
    procedure TForm1.FormCreate(Sender: TObject);
    begin
       ...
       IdleCount := 0;
       Application.OnIdle := ApplicationEvents1Idle;//add this
       Timer1.Enabled := False;//default timer.interval is 1000 which is every second.  
       ...
    end;
    Double Click the Timer component on your form to add the OnTimer Method and add code.

    Code:
    procedure TForm1.Timer1Timer(Sender: TObject);
    begin
       if IdleCount = (Some Number of your choosing) then
       begin
          Timer1.Enabled := False;
          //logout here
       end
       else
          Inc(IdleCount);
    end;
    If you keep the timer interval to 1000, then "some number of your choosing" will be the number of seconds of idle time. you can of course change the interval, (every 1000 = 1 second).

    Now you need to write the event handler for the OnIdle event which fires (as we'll use it) once when the application goes idle.

    Code:
    procedure TForm1.ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
    begin
       IdleCount := 0;
       //when the application first goes idle, reset idlecount to 0, and let the timer increment it and log you out if if gets past a certain amount of time.
       Timer.Enabled := True;//turn on the timer when it first goes idle
    end;
    Last edited by majlumbo; April 25th, 2012 at 09:44 AM.
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2012
    Posts
    155
    Rep Power
    3
    I just wrote a tutorial addressing the essence of the problem (i.e. detecting used inactivity). Please check it out here:

    Detect User Idle And Do Something After Some Time Ellapsed

    Note: The tutorial addresses both detecting "local" user inactivity and system wide user inactivity. For system wide detection I did not offer to use hook. Just use a simple windows call.

    Cheers!

IMN logo majestic logo threadwatch logo seochat tools logo