* * *

Author Topic: Create mainform after login form closes  (Read 606 times)

talorigomat

  • Jr. Member
  • **
  • Posts: 94
Create mainform after login form closes
« on: October 06, 2017, 03:03:34 pm »
I'm trying to display a login form and then only create and display the application main form if password is correct. however I am getting a "failed to create win32 control error: 1407 : cannot find class in file win32 controls.pp in line 217"

The login form  has the following  code which I found on a Delphi site
Code: Pascal  [Select]
  1. unit login;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TLoginForm }
  13.  
  14.   TLoginForm = class(TForm)
  15.     LogInButton: TButton;
  16.     passwordEdit: TEdit;
  17.     pwdLabel: TLabel;
  18.     procedure LogInButtonClick(Sender: TObject);
  19.   private
  20.  
  21.   public
  22.     class function Execute : boolean;
  23.   end;
  24.  
  25. var
  26.   LoginForm: TLoginForm;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TLoginForm }
  33.  
  34. class function TLoginForm.Execute: boolean;
  35. begin
  36.   with TLoginForm.Create(nil) do
  37.   try
  38.     Result := ShowModal = mrOk;
  39.   finally
  40.     Free;
  41.   end;
  42. end;
  43.  
  44. procedure TLoginForm.LogInButtonClick(Sender: TObject);
  45. begin
  46.   if passwordEdit.Text = 'LetMeIn' then
  47.     ModalResult := mrOK
  48.   else
  49.     ModalResult := mrAbort;
  50. end;
  51.  
  52. end.
  53.  

And the project source file ha the following
Code: Pascal  [Select]
  1.  
  2. program project1;
  3.  
  4. {$mode objfpc}{$H+}
  5.  
  6. uses
  7.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  8.   cthreads,
  9.   {$ENDIF}{$ENDIF}
  10.   Interfaces, // this includes the LCL widgetset
  11.   Forms, main, login
  12.   { you can add units after this };
  13.  
  14. {$R *.res}
  15.  
  16. begin
  17.   if TLoginForm.Execute then
  18.     begin
  19.       RequireDerivedFormResource:=True;
  20.       Application.Initialize;
  21.       Application.CreateForm(TTMainForm, TMainForm);
  22.       Application.Run;
  23.     end
  24.   else
  25.     Application.MessageBox('Not allowed in','Password Protected');
  26. end.
  27.  
Lazarus 1.8.0Rc4, Windows 10

ASerge

  • Sr. Member
  • ****
  • Posts: 472
Re: Create mainform after login form closes
« Reply #1 on: October 06, 2017, 03:32:54 pm »
TApplication.Initialize initializes the widgetset (and more).
Code: Pascal  [Select]
  1. ...
  2. begin
  3.   RequireDerivedFormResource:=True;
  4.   Application.Initialize; // Need first!
  5.   if TLoginForm.Execute then
  6.   begin
  7.     Application.CreateForm(TTMainForm, TMainForm);
  8.     Application.Run;
  9.   end
  10.   else
  11.     Application.MessageBox('Not allowed in','Password Protected');
  12. end.
  13.  

howardpc

  • Hero Member
  • *****
  • Posts: 2421
Re: Create mainform after login form closes
« Reply #2 on: October 06, 2017, 04:09:56 pm »
Two minor points:

You don't need the global LoginForm variable which Lazarus added to your login unit - it should be deleted.
Unfortunately the Application.MessageBox routine does not take account of the length of the window title when sizing the dialog, so you will probably need to do something like
Code: Pascal  [Select]
  1. Application.MessageBox('Not allowed in       ','Password protected');
in order to read the full window title, else it will be truncated.

talorigomat

  • Jr. Member
  • **
  • Posts: 94
Re: Create mainform after login form closes
« Reply #3 on: October 06, 2017, 05:01:49 pm »
Thank you both.  I made the changes as suggested.  When I run the program I get the error:
"Raised exception class 'EResNotFound' with message: For resource TLoginForm not found.  For rosourceless forms Create new constructor must be used.  See the global variable RequiredFormResource"

If I change LoginForm.Execute methos to use the Create new method.
Code: Pascal  [Select]
  1. class function TLoginForm.Execute: boolean;
  2. begin
  3.   with TLoginForm.CreateNew(nil) do // < changed from TLoginForm.Create(nil)
  4.   try
  5.     Result := ShowModal = mrOk;
  6.   finally
  7.     Free;
  8.   end;
  9. end;
  10.  

The program runs but the form that is first displayed has no cotrols on it and when closed the application stops

I'm using lazarus 1.8.0 RC4 on Window 10.  I'll check my signature to reflect this
Lazarus 1.8.0Rc4, Windows 10

FTurtle

  • Full Member
  • ***
  • Posts: 204
Re: Create mainform after login form closes
« Reply #4 on: October 06, 2017, 05:22:05 pm »
If your form made in designer then add to code {$R *.lfm} and use Create :

Code: Pascal  [Select]
  1. implementation
  2.  
  3. {$R *.lfm}
  4.  

howardpc

  • Hero Member
  • *****
  • Posts: 2421
Re: Create mainform after login form closes
« Reply #5 on: October 06, 2017, 05:36:15 pm »
The Delphi code you found assumed you had created unit login as a form which had its appropriate .dfm resource file (.lfm in Lazarus).

If you want to have a resourceless login form you have to instantiate the form's controls in code. Something along these lines:
Code: Pascal  [Select]
  1.   unit uResourcelessLoginForm;
  2.  
  3.   {$mode objfpc}{$H+}
  4.  
  5.   interface
  6.  
  7.   uses
  8.     SysUtils, Forms, Controls, StdCtrls;
  9.  
  10.   type
  11.  
  12.     { TResourcelessLoginForm }
  13.  
  14.     TResourcelessLoginForm = class(TForm)
  15.     private
  16.       LoginButton: TButton;
  17.       PasswordEdit: TEdit;
  18.       PasswordLabel: TLabel;
  19.       procedure LoginButtonClick(Sender: TObject);
  20.       procedure SetupGUI;
  21.     public
  22.       constructor Create; reintroduce;
  23.     end;
  24.  
  25.     function LoginIsCorrectDlg: Boolean;
  26.  
  27.   implementation
  28.  
  29.   function LoginIsCorrectDlg: Boolean;
  30.   var
  31.     dlg: TResourcelessLoginForm;
  32.   begin
  33.     dlg:=TResourcelessLoginForm.Create;
  34.     try
  35.       Exit(dlg.ShowModal = mrOK);
  36.     finally
  37.       dlg.Free;
  38.       dlg:=Nil;
  39.     end;
  40.   end;
  41.  
  42.   { TResourcelessLoginForm }
  43.  
  44.   constructor TResourcelessLoginForm.Create;
  45.   begin
  46.     inherited CreateNew(Nil);
  47.     AutoSize:=True;
  48.     Caption:='Login';
  49.     Position:=poScreenCenter;
  50.     BorderStyle:=bsDialog;
  51.     SetupGUI;
  52.   end;
  53.  
  54.   procedure TResourcelessLoginForm.LoginButtonClick(Sender: TObject);
  55.   begin
  56.     if (PasswordEdit.Text = 'LetMeIn') then
  57.       ModalResult:=mrOK
  58.     else ModalResult:=mrCancel;
  59.   end;
  60.  
  61.   procedure TResourcelessLoginForm.SetupGUI;
  62.   begin
  63.     PasswordLabel:=TLabel.Create(Self);
  64.     with PasswordLabel do begin
  65.       AnchorSideLeft.Control:=Self;
  66.       AnchorSideTop.Control:=Self;
  67.       BorderSpacing.Around:=12;
  68.       Caption:='Password:';
  69.       Parent:=Self;
  70.     end;
  71.  
  72.     PasswordEdit:=TEdit.Create(Self);
  73.     with PasswordEdit do begin
  74.       AnchorSideLeft.Control:=Self;
  75.       AnchorSideTop.Control:=PasswordLabel;
  76.       AnchorSideTop.Side:=asrBottom;
  77.       Width:=150;
  78.       BorderSpacing.Around:=12;
  79.       EchoMode:=emPassword;
  80.       PasswordChar:='*';
  81.       TabOrder:=0;
  82.       Parent:=Self;
  83.     end;
  84.  
  85.     LoginButton:=TButton.Create(Self);
  86.     with LoginButton do begin
  87.       AnchorSideLeft.Control:=PasswordEdit;
  88.       AnchorSideLeft.Side:=asrRight;
  89.       AnchorSideTop.Control:=PasswordEdit;
  90.       AnchorSideTop.Side:=asrCenter;
  91.       AutoSize:=True;
  92.       BorderSpacing.Around:=12;
  93.       Caption:='LoginButton';
  94.       OnClick:=@LoginButtonClick;
  95.       TabOrder:=1;
  96.       Parent:=Self;
  97.     end;
  98.   end;
  99.  
  100. end.

Your .lpr would then need to be as follows:
Code: Pascal  [Select]
  1. program project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   Interfaces, Forms, Unit1, uResourcelessLoginForm;
  7.  
  8. {$R *.res}
  9.  
  10. begin
  11.   RequireDerivedFormResource:=True;
  12.   Application.Initialize;
  13.   if LoginIsCorrectDlg then begin
  14.     Application.CreateForm(TForm1, Form1);
  15.     Application.Run;
  16.   end
  17.   else Application.MessageBox('Not allowed in       ','Password protected');
  18. end.

talorigomat

  • Jr. Member
  • **
  • Posts: 94
Re: Create mainform after login form closes
« Reply #6 on: October 06, 2017, 06:15:31 pm »
Thanks Howardpc.  Your example does work.  I wasn't really trying to make a resourceless form.  I had created both forms with the designer so they both have a .lfm resource file, hence I'm not sure why I had this error.


« Last Edit: October 06, 2017, 06:17:03 pm by talorigomat »
Lazarus 1.8.0Rc4, Windows 10

howardpc

  • Hero Member
  • *****
  • Posts: 2421
Re: Create mainform after login form closes
« Reply #7 on: October 06, 2017, 07:20:34 pm »
EResNotFound occurs either because the .lfm resource is not where the compiler expects it, or because it finds it but it cannot read it (or it contains errors or garbage); or, as FTurtle pointed out because you omitted the {$R *.lfm} directive in one of your form units. The latter is unlikely since Lazarus automatically inserts the directive for you whenever you create a new form with File->New Form, so would only happen if you (perhaps) accidentally deleted that source line.
« Last Edit: October 06, 2017, 07:22:52 pm by howardpc »

 

Recent

Get Lazarus at SourceForge.net. Fast, secure and Free Open Source software downloads Open Hub project report for Lazarus