home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 September / Chip_2001-09_cd1.bin / zkuste / delphi / kolekce / d6 / RX275D6.ZIP / Units / rxlogin.pas < prev    next >
Pascal/Delphi Source File  |  1999-10-12  |  17KB  |  604 lines

  1. {*******************************************************}
  2. {                                                       }
  3. {         Delphi VCL Extensions (RX)                    }
  4. {                                                       }
  5. {         Copyright (c) 1995, 1996 AO ROSNO             }
  6. {         Copyright (c) 1997, 1998 Master-Bank          }
  7. {                                                       }
  8. {*******************************************************}
  9.  
  10. unit RxLogin;
  11.  
  12. {$I RX.INC}
  13.  
  14. interface
  15.  
  16. uses {$IFDEF WIN32} Windows, {$ELSE} WinTypes, WinProcs, {$ENDIF} SysUtils,
  17.   Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls,
  18.   Buttons;
  19.  
  20. type
  21.   TUpdateCaption = (ucNoChange, ucAppTitle, ucFormCaption);
  22.   TRxLoginEvent = procedure(Sender: TObject; const UserName, Password: string;
  23.     var AllowLogin: Boolean) of object;
  24.   TCheckUnlockEvent = function(const Password: string): Boolean of object;
  25.   TUnlockAppEvent = procedure(Sender: TObject; const UserName,
  26.     Password: string; var AllowUnlock: Boolean) of object;
  27.  
  28.   TRxLoginForm = class;
  29.  
  30. { TRxCustomLogin }
  31.  
  32.   TRxCustomLogin = class(TComponent)
  33.   private
  34.     FActive: Boolean;
  35.     FAttemptNumber: Integer;
  36.     FLoggedUser: PString;
  37.     FMaxPasswordLen: Integer;
  38.     FAllowEmpty: Boolean;
  39.     FUpdateCaption: TUpdateCaption;
  40.     FIniFileName: PString;
  41.     FUseRegistry: Boolean;
  42.     FLocked: Boolean;
  43.     FUnlockDlgShowing: Boolean;
  44.     FSaveOnRestore: TNotifyEvent;
  45.     FAfterLogin: TNotifyEvent;
  46.     FBeforeLogin: TNotifyEvent;
  47.     FOnUnlock: TCheckUnlockEvent;
  48.     FOnUnlockApp: TUnlockAppEvent;
  49.     FOnIconDblClick: TNotifyEvent;
  50.     function GetLoggedUser: string;
  51.     function GetIniFileName: string;
  52.     procedure SetIniFileName(const Value: string);
  53.     function UnlockHook(var Message: TMessage): Boolean;
  54.   protected
  55.     function CheckUnlock(const UserName, Password: string): Boolean; dynamic;
  56.     function CreateLoginForm(UnlockMode: Boolean): TRxLoginForm; virtual;
  57.     procedure DoAfterLogin; dynamic;
  58.     procedure DoBeforeLogin; dynamic;
  59.     procedure DoIconDblCLick(Sender: TObject); dynamic;
  60.     function DoLogin(var UserName: string): Boolean; virtual; abstract;
  61.     function DoUnlockDialog: Boolean; virtual;
  62.     procedure SetLoggedUser(const Value: string);
  63.     procedure DoUpdateCaption;
  64.     procedure UnlockOkClick(Sender: TObject);
  65.     property Active: Boolean read FActive write FActive default True;
  66.     property AllowEmptyPassword: Boolean read FAllowEmpty write FAllowEmpty default True;
  67.     property AttemptNumber: Integer read FAttemptNumber write FAttemptNumber default 3;
  68.     property IniFileName: string read GetIniFileName write SetIniFileName;
  69.     property MaxPasswordLen: Integer read FMaxPasswordLen write FMaxPasswordLen default 0;
  70.     property UpdateCaption: TUpdateCaption read FUpdateCaption write FUpdateCaption default ucNoChange;
  71.     property UseRegistry: Boolean read FUseRegistry write FUseRegistry default False;
  72.     property AfterLogin: TNotifyEvent read FAfterLogin write FAfterLogin;
  73.     property BeforeLogin: TNotifyEvent read FBeforeLogin write FBeforeLogin;
  74.     property OnUnlock: TCheckUnlockEvent read FOnUnlock write FOnUnlock; { obsolete }
  75.     property OnUnlockApp: TUnlockAppEvent read FOnUnlockApp write FOnUnlockApp;
  76.     property OnIconDblClick: TNotifyEvent read FOnIconDblClick write FOnIconDblClick;
  77.   public
  78.     constructor Create(AOwner: TComponent); override;
  79.     destructor Destroy; override;
  80.     function Login: Boolean; virtual;
  81.     procedure TerminateApplication;
  82.     procedure Lock;
  83.     property LoggedUser: string read GetLoggedUser;
  84.   end;
  85.  
  86. { TRxLoginDialog }
  87.  
  88.   TRxLoginDialog = class(TRxCustomLogin)
  89.   private
  90.     FOnCheckUser: TRxLoginEvent;
  91.     procedure OkButtonClick(Sender: TObject);
  92.     procedure WriteUserName(const UserName: string);
  93.     function ReadUserName(const UserName: string): string;
  94.   protected
  95.     function DoCheckUser(const UserName, Password: string): Boolean; dynamic;
  96.     function DoLogin(var UserName: string): Boolean; override;
  97.     procedure Loaded; override;
  98.   published
  99.     property Active;
  100.     property AttemptNumber;
  101.     property IniFileName;
  102.     property MaxPasswordLen;
  103.     property UpdateCaption;
  104.     property UseRegistry;
  105.     property OnCheckUser: TRxLoginEvent read FOnCheckUser write FOnCheckUser;
  106.     property AfterLogin;
  107.     property BeforeLogin;
  108.     property OnUnlockApp;
  109.     property OnIconDblClick;
  110.   end;
  111.  
  112. { TRxLoginForm }
  113.  
  114.   TRxLoginForm = class(TForm)
  115.     AppIcon: TImage;
  116.     KeyImage: TImage;
  117.     HintLabel: TLabel;
  118.     UserNameLabel: TLabel;
  119.     PasswordLabel: TLabel;
  120.     UserNameEdit: TEdit;
  121.     PasswordEdit: TEdit;
  122.     AppTitleLabel: TLabel;
  123.     OkBtn: TButton;
  124.     CancelBtn: TButton;
  125.     CustomLabel: TLabel;
  126.     CustomCombo: TComboBox;
  127.     procedure FormCreate(Sender: TObject);
  128.     procedure OkBtnClick(Sender: TObject);
  129.     procedure FormShow(Sender: TObject);
  130.   private
  131.     { Private declarations }
  132.     FSelectDatabase: Boolean;
  133.     FUnlockMode: Boolean;
  134.     FAttempt: Integer;
  135.     FOnFormShow: TNotifyEvent;
  136.     FOnOkClick: TNotifyEvent;
  137.   public
  138.     { Public declarations }
  139.     AttemptNumber: Integer;
  140.     property Attempt: Integer read FAttempt;
  141.     property SelectDatabase: Boolean read FSelectDatabase write FSelectDatabase;
  142.     property OnFormShow: TNotifyEvent read FOnFormShow write FOnFormShow;
  143.     property OnOkClick: TNotifyEvent read FOnOkClick write FOnOkClick;
  144.   end;
  145.  
  146. function CreateLoginDialog(UnlockMode, ASelectDatabase: Boolean;
  147.   FormShowEvent, OkClickEvent: TNotifyEvent): TRxLoginForm;
  148.  
  149. implementation
  150.  
  151. uses {$IFDEF WIN32} Registry, {$ENDIF} IniFiles, AppUtils, RxDConst,
  152.   Consts, VclUtils, RxConst;
  153.  
  154. {$R *.DFM}
  155.  
  156. const
  157.   keyLoginSection  = 'Login Dialog';
  158.   keyLastLoginUserName = 'Last Logged User';
  159.  
  160. function CreateLoginDialog(UnlockMode, ASelectDatabase: Boolean;
  161.   FormShowEvent, OkClickEvent: TNotifyEvent): TRxLoginForm;
  162. begin
  163.   Result := TRxLoginForm.Create(Application);
  164.   with Result do begin
  165.     FSelectDatabase := ASelectDatabase;
  166.     FUnlockMode := UnlockMode;
  167.     if FUnlockMode then begin
  168.       FormStyle := fsNormal;
  169.       FSelectDatabase := False;
  170.     end
  171.     else begin
  172.       FormStyle := fsStayOnTop;
  173.     end;
  174.     OnFormShow := FormShowEvent;
  175.     OnOkClick := OkClickEvent;
  176.   end;
  177. end;
  178.  
  179. { TRxCustomLogin }
  180.  
  181. constructor TRxCustomLogin.Create(AOwner: TComponent);
  182. begin
  183.   inherited Create(AOwner);
  184.   FIniFileName := NullStr;
  185.   FLoggedUser := NullStr;
  186.   FActive := True;
  187.   FAttemptNumber := 3;
  188.   FAllowEmpty := True;
  189.   FUseRegistry := False;
  190. end;
  191.  
  192. destructor TRxCustomLogin.Destroy;
  193. begin
  194.   if FLocked then begin
  195.     Application.UnhookMainWindow(UnlockHook);
  196.     FLocked := False;
  197.   end;
  198.   DisposeStr(FLoggedUser);
  199.   DisposeStr(FIniFileName);
  200.   inherited Destroy;
  201. end;
  202.  
  203. function TRxCustomLogin.GetIniFileName: string;
  204. begin
  205.   Result := FIniFileName^;
  206.   if (Result = '') and not (csDesigning in ComponentState) then begin
  207. {$IFDEF WIN32}
  208.     if UseRegistry then Result := GetDefaultIniRegKey
  209.     else Result := GetDefaultIniName;
  210. {$ELSE}
  211.     Result := GetDefaultIniName;
  212. {$ENDIF}
  213.   end;
  214. end;
  215.  
  216. procedure TRxCustomLogin.SetIniFileName(const Value: string);
  217. begin
  218.   AssignStr(FIniFileName, Value);
  219. end;
  220.  
  221. function TRxCustomLogin.GetLoggedUser: string;
  222. begin
  223.   Result := FLoggedUser^;
  224. end;
  225.  
  226. procedure TRxCustomLogin.SetLoggedUser(const Value: string);
  227. begin
  228.   AssignStr(FLoggedUser, Value);
  229. end;
  230.  
  231. procedure TRxCustomLogin.DoAfterLogin;
  232. begin
  233.   if Assigned(FAfterLogin) then FAfterLogin(Self);
  234. end;
  235.  
  236. procedure TRxCustomLogin.DoBeforeLogin;
  237. begin
  238.   if Assigned(FBeforeLogin) then FBeforeLogin(Self);
  239. end;
  240.  
  241. procedure TRxCustomLogin.DoIconDblCLick(Sender: TObject);
  242. begin
  243.   if Assigned(FOnIconDblClick) then FOnIconDblClick(Self);
  244. end;
  245.  
  246. procedure TRxCustomLogin.DoUpdateCaption;
  247. var
  248.   F: TForm;
  249. begin
  250.   F := Application.MainForm;
  251.   if (F = nil) and (Owner is TForm) then F := Owner as TForm;
  252.   if (F <> nil) and (LoggedUser <> '') then
  253.     case UpdateCaption of
  254.       ucAppTitle:
  255.         F.Caption := Format('%s (%s)', [Application.Title, LoggedUser]);
  256.       ucFormCaption:
  257.         begin
  258.           F.Caption := Format('%s (%s)', [F.Caption, LoggedUser]);
  259.           UpdateCaption := ucNoChange;
  260.         end;
  261.     end;
  262. end;
  263.  
  264. function TRxCustomLogin.Login: Boolean;
  265. var
  266.   LoginName: string;
  267. begin
  268.   LoginName := EmptyStr;
  269.   DoBeforeLogin;
  270.   Result := DoLogin(LoginName);
  271.   if Result then begin
  272.     SetLoggedUser(LoginName);
  273.     DoUpdateCaption;
  274.     DoAfterLogin;
  275.   end;
  276. end;
  277.  
  278. procedure TRxCustomLogin.Lock;
  279. begin
  280.   FSaveOnRestore := Application.OnRestore;
  281.   Application.Minimize;
  282.   Application.HookMainWindow(UnlockHook);
  283.   FLocked := True;
  284. end;
  285.  
  286. procedure TRxCustomLogin.TerminateApplication;
  287. begin
  288.   with Application do begin
  289. {$IFDEF WIN32}
  290.     ShowMainForm := False;
  291. {$ENDIF}
  292.     if Handle <> 0 then ShowOwnedPopups(Handle, False);
  293.     Terminate;
  294.   end;
  295. {$IFDEF WIN32}
  296.   CallTerminateProcs;
  297. {$ENDIF}
  298. {$IFNDEF RX_D3}
  299.   Halt(10);
  300. {$ENDIF}
  301. end;
  302.  
  303. procedure TRxCustomLogin.UnlockOkClick(Sender: TObject);
  304. var
  305.   Ok: Boolean;
  306. begin
  307.   with TRxLoginForm(Sender) do begin
  308.     Ok := False;
  309.     try
  310.       Ok := CheckUnlock(UserNameEdit.Text, PasswordEdit.Text);
  311.     except
  312.       Application.HandleException(Self);
  313.     end;
  314.     if Ok then ModalResult := mrOk
  315.     else ModalResult := mrCancel;
  316.   end;
  317. end;
  318.  
  319. function TRxCustomLogin.CheckUnlock(const UserName, Password: string): Boolean;
  320. begin
  321.   Result := True;
  322.   if Assigned(FOnUnlockApp) then
  323.     FOnUnlockApp(Self, UserName, Password, Result)
  324.   else if Assigned(FOnUnlock) then
  325.     Result := FOnUnlock(Password);
  326. end;
  327.  
  328. function TRxCustomLogin.CreateLoginForm(UnlockMode: Boolean): TRxLoginForm;
  329. begin
  330.   Result := TRxLoginForm.Create(Application);
  331.   with Result do begin
  332.     FUnlockMode := UnlockMode;
  333.     if FUnlockMode then begin
  334.       FormStyle := fsNormal;
  335.       FSelectDatabase := False;
  336.     end
  337.     else FormStyle := fsStayOnTop;
  338.     if Assigned(Self.FOnIconDblClick) then begin
  339.       with AppIcon do begin
  340.         OnDblClick := DoIconDblClick;
  341.         Cursor := crHand;
  342.       end;
  343.       with KeyImage do begin
  344.         OnDblClick := DoIconDblClick;
  345.         Cursor := crHand;
  346.       end;
  347.     end;
  348.     PasswordEdit.MaxLength := FMaxPasswordLen;
  349.     AttemptNumber := Self.AttemptNumber;
  350.   end;
  351. end;
  352.  
  353. function TRxCustomLogin.DoUnlockDialog: Boolean;
  354. begin
  355.   with CreateLoginForm(True) do
  356.   try
  357.     OnFormShow := nil;
  358.     OnOkClick := UnlockOkClick;
  359.     with UserNameEdit do begin
  360.       Text := LoggedUser;
  361.       ReadOnly := True;
  362.       Font.Color := clGrayText;
  363.     end;
  364.     Result := ShowModal = mrOk;
  365.   finally
  366.     Free;
  367.   end;
  368. end;
  369.  
  370. function TRxCustomLogin.UnlockHook(var Message: TMessage): Boolean;
  371.  
  372.   function DoUnlock: Boolean;
  373.   var
  374.     Popup: HWnd;
  375.   begin
  376.     with Application do
  377.       if IsWindowVisible(Handle) and IsWindowEnabled(Handle) then
  378. {$IFDEF WIN32}
  379.         SetForegroundWindow(Handle);
  380. {$ELSE}
  381.         BringWindowToTop(Handle);
  382. {$ENDIF}
  383.     if FUnlockDlgShowing then begin
  384.       Popup := GetLastActivePopup(Application.Handle);
  385.       if (Popup <> 0) and IsWindowVisible(Popup) and
  386.         (WindowClassName(Popup) = TRxLoginForm.ClassName) then
  387.       begin
  388. {$IFDEF WIN32}
  389.         SetForegroundWindow(Popup);
  390. {$ELSE}
  391.         BringWindowToTop(Popup);
  392. {$ENDIF}
  393.       end;
  394.       Result := False;
  395.       Exit;
  396.     end;
  397.     FUnlockDlgShowing := True;
  398.     try
  399.       Result := DoUnlockDialog;
  400.     finally
  401.       FUnlockDlgShowing := False;
  402.     end;
  403.     if Result then begin
  404.       Application.UnhookMainWindow(UnlockHook);
  405.       FLocked := False;
  406.     end;
  407.   end;
  408.  
  409. begin
  410.   Result := False;
  411.   if not FLocked then Exit;
  412.   with Message do begin
  413.     case Msg of
  414.       WM_QUERYOPEN:
  415.         begin
  416.           UnlockHook := not DoUnlock;
  417.         end;
  418.       WM_SHOWWINDOW:
  419.         if Bool(WParam) then begin
  420.           UnlockHook := not DoUnlock;
  421.         end;
  422.       WM_SYSCOMMAND:
  423.         if (WParam and $FFF0 = SC_RESTORE) or
  424.           (WParam and $FFF0 = SC_ZOOM) then
  425.         begin
  426.           UnlockHook := not DoUnlock;
  427.         end;
  428.     end;
  429.   end;
  430. end;
  431.  
  432. { TRxLoginDialog }
  433.  
  434. procedure TRxLoginDialog.Loaded;
  435. var
  436.   Loading: Boolean;
  437. begin
  438.   Loading := csLoading in ComponentState;
  439.   inherited Loaded;
  440.   if not (csDesigning in ComponentState) and Loading then begin
  441.     if Active and not Login then
  442.       TerminateApplication;
  443.   end;
  444. end;
  445.  
  446. procedure TRxLoginDialog.OkButtonClick(Sender: TObject);
  447. var
  448.   SetCursor: Boolean;
  449. begin
  450.   with TRxLoginForm(Sender) do begin
  451. {$IFDEF WIN32}
  452.     SetCursor := GetCurrentThreadID = MainThreadID;
  453. {$ELSE}
  454.     SetCursor := True;
  455. {$ENDIF}
  456.     try
  457.       if SetCursor then Screen.Cursor := crHourGlass;
  458.       try
  459.         if DoCheckUser(UserNameEdit.Text, PasswordEdit.Text) then
  460.           ModalResult := mrOk
  461.         else ModalResult := mrNone;
  462.       finally
  463.         if SetCursor then Screen.Cursor := crDefault;
  464.       end;
  465.     except
  466.       Application.HandleException(Self);
  467.     end;
  468.   end;
  469. end;
  470.  
  471. function TRxLoginDialog.DoCheckUser(const UserName, Password: string): Boolean;
  472. begin
  473.   Result := True;
  474.   if Assigned(FOnCheckUser) then
  475.     FOnCheckUser(Self, UserName, Password, Result);
  476. end;
  477.  
  478. procedure TRxLoginDialog.WriteUserName(const UserName: string);
  479. var
  480.   Ini: TObject;
  481. begin
  482.   try
  483. {$IFDEF WIN32}
  484.     if UseRegistry then Ini := TRegIniFile.Create(IniFileName)
  485.     else Ini := TIniFile.Create(IniFileName);
  486. {$ELSE}
  487.     Ini := TIniFile.Create(IniFileName);
  488. {$ENDIF}
  489.     try
  490.       IniWriteString(Ini, keyLoginSection, keyLastLoginUserName, UserName);
  491.     finally
  492.       Ini.Free;
  493.     end;
  494.   except
  495.   end;
  496. end;
  497.  
  498. function TRxLoginDialog.ReadUserName(const UserName: string): string;
  499. var
  500.   Ini: TObject;
  501. begin
  502.   try
  503. {$IFDEF WIN32}
  504.     if UseRegistry then begin
  505.       Ini := TRegIniFile.Create(IniFileName);
  506. {$IFDEF RX_D5}
  507.       TRegIniFile(Ini).Access := KEY_READ;
  508. {$ENDIF}
  509.     end
  510.     else 
  511.       Ini := TIniFile.Create(IniFileName);
  512. {$ELSE}
  513.     Ini := TIniFile.Create(IniFileName);
  514. {$ENDIF}
  515.     try
  516.       Result := IniReadString(Ini, keyLoginSection, keyLastLoginUserName,
  517.         UserName);
  518.     finally
  519.       Ini.Free;
  520.     end;
  521.   except
  522.     Result := UserName;
  523.   end;
  524. end;
  525.  
  526. function TRxLoginDialog.DoLogin(var UserName: string): Boolean;
  527. begin
  528.   try
  529.     with CreateLoginForm(False) do
  530.     try
  531.       OnOkClick := Self.OkButtonClick;
  532.       UserName := ReadUserName(UserName);
  533.       UserNameEdit.Text := UserName;
  534.       Result := (ShowModal = mrOk);
  535.       if Result then begin
  536.         UserName := UserNameEdit.Text;
  537.         WriteUserName(UserName);
  538.       end;
  539.     finally
  540.       Free;
  541.     end;
  542.   except
  543.     Application.HandleException(Self);
  544.     Result := False;
  545.   end;
  546. end;
  547.  
  548. { TRxLoginForm }
  549.  
  550. procedure TRxLoginForm.FormCreate(Sender: TObject);
  551. begin
  552.   Icon := Application.Icon;
  553.   if Icon.Empty then Icon.Handle := LoadIcon(0, IDI_APPLICATION);
  554.   AppIcon.Picture.Assign(Icon);
  555.   AppTitleLabel.Caption := FmtLoadStr(SAppTitleLabel, [Application.Title]);
  556.   PasswordLabel.Caption := LoadStr(SPasswordLabel);
  557.   UserNameLabel.Caption := LoadStr(SUserNameLabel);
  558.   OkBtn.Caption := ResStr(SOKButton);
  559.   CancelBtn.Caption := ResStr(SCancelButton);
  560. end;
  561.  
  562. procedure TRxLoginForm.OkBtnClick(Sender: TObject);
  563. begin
  564.   Inc(FAttempt);
  565.   if Assigned(FOnOkClick) then FOnOkClick(Self)
  566.   else ModalResult := mrOk;
  567.   if (ModalResult <> mrOk) and (FAttempt >= AttemptNumber) then
  568.     ModalResult := mrCancel;
  569. end;
  570.  
  571. procedure TRxLoginForm.FormShow(Sender: TObject);
  572. var
  573.   I: Integer;
  574.   S: string;
  575. begin
  576.   if FSelectDatabase then begin
  577.     ClientHeight := CustomCombo.Top + PasswordEdit.Top - UserNameEdit.Top;
  578.     S := LoadStr(SDatabaseName);
  579.     I := Pos(':', S);
  580.     if I = 0 then I := Length(S);
  581.     CustomLabel.Caption := '&' + Copy(S, 1, I);
  582.   end
  583.   else begin
  584.     ClientHeight := PasswordEdit.Top + PasswordEdit.Top - UserNameEdit.Top;
  585.     CustomLabel.Visible := False;
  586.     CustomCombo.Visible := False;
  587.   end;
  588.   if not FUnlockMode then begin
  589.     HintLabel.Caption := LoadStr(SHintLabel);
  590.     Caption := LoadStr(SRegistration);
  591.   end
  592.   else begin
  593.     HintLabel.Caption := LoadStr(SUnlockHint);
  594.     Caption := LoadStr(SUnlockCaption);
  595.   end;
  596.   if (UserNameEdit.Text = EmptyStr) and not FUnlockMode then
  597.     ActiveControl := UserNameEdit
  598.   else 
  599.     ActiveControl := PasswordEdit;
  600.   if Assigned(FOnFormShow) then FOnFormShow(Self);
  601.   FAttempt := 0;
  602. end;
  603.  
  604. end.