RXLOGIN.PAS
Upload User: aomate168
Upload Date: 2021-08-05
Package Size: 826k
Code Size: 16k
Category:

Windows Develop

Development Platform:

C++ Builder

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