Link to home
Start Free TrialLog in
Avatar of delphibeginner
delphibeginnerFlag for Netherlands

asked on

Run screen once at main app startup created with Delphi

I have an app created with delphi 2010, and added a form that users need to enter their name, before the app can start.
This works (it's being saved in a file), but this form should only run once (if the name is being entered and saved).

How can I do this, so the form won't show up everytime the app starts?

Thanks.
Avatar of systan
systan
Flag of Philippines image

program Project1;

uses
windows,
  Forms,
  Unit1 in 'Unit1.pas' {Form1};


var
Mutex : THandle;

{$R *.res}

begin
Mutex := CreateMutex(nil, True, 'yourprogramnameid');
  if (Mutex <> 0) and (GetLastError = 0) then
  begin
   Application.Initialize;
   Application.CreateForm(TForm1, Form1);
   Application.Run;
  if Mutex <> 0 then CloseHandle(Mutex);
  end;

end.
I do this in several apps I have written.  Basically, when the MainForm comes up, in the On Show event, I call a LogIn form that lets the user log in.  If the log in is successful, I set a boolean variable (which I usually make as a completely, globally public variable in the DataModaule because that module is connected to virtually everything anyway ;-).  The default for the Boolean (let's call it LoggedIn) is False, so, when the app first starts and performs the On Show procedure, checking the Boolean for False causes the LogIn form to be called.  After LoggedIn is set to True, the Login form is not called.
This has the added benefit of allow you to provide a means for a user to log out if they are about to walk away from their desk for a little while.  That lets them leave teh app "up" while providing the security of not leaving it in a logged-in state.
I have attached a sample LogIn form.  This one uses a coding pattern that I learned from a Borland Certified Delphi Instructor Instructor (and, no, I didn't stutter in my typing ;-).  By having the fully public function to call for initiating the log in, this code is decoupled from any specific project and reusable for multiple projects.  Use with my blessings (and, hopefully, giving credit to me in your applications notes ;-).  If you like it, contact me and I'll provide a slightly more documented version.  (I also have a decoupled AboutBox and a couple of other units that I freely provide with the only payment being credit for them in any application notes where they are used. ;-)

TWGUserLogin.zip
or if I got it wrong,

how about this one:
//

implementation
uses unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
form2.ShowModal; // second form
end;


or
//clicked a button to save
if files are saved? then
begin
form2.Destroy;
end;
systan,
Isn't that kind of the hard way around the problem. ;-)
 
ok, sorry, if i got it all wrong
Avatar of Emmanuel PASQUIER
Hi guys, I suspect you got the question wrong. He does not want the login to occur only once per application session, but only once per station, the first time the app is run, period.

// in your project main :

begin
 Application.Initialize;
 Application.CreateForm(TMainForm, MainForm);
 Application.CreateForm(TLoginForm, LoginForm);
 Application.Run;
end.

// in you main form onActivate :

procedure TMainForm.FormActivate(Sender: TObject);
begin
 if Not LoginForm.IsLogged 
  Then Close; // will close the application if a pb occured in Logged
end;

// in your Login form :

function TLoginForm.IsLogged:Boolean;
begin
// implement this as you see fit
 Result:=FileExists(FileWhereLoginIsSaved) And LoginIsValidIn(FileWhereLoginIsSaved);
 if Not Result Then 
  begin
   MainForm.Visible:=False;
   Result:=(ShowModal=mrOK) and (edtLogin.Text<>'');
   MainForm.Visible:=True;
  end;
end;

and in a OK button click event you save your login and return ModalResult:=mrOk (if not automatic by the kind of button)

Open in new window

Read the file you write !

If it contains the credentials you want then show the form else don't show it.
Ok, how about this one:  I hope I get it now :)

//in unit1,form1(which is the login name form)
implementation
uses unit2;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
if (edit1.text<>'') and (edit2.text<>'') then //or if the names are right
begin
form2.Show; //form2.Showmodal;  //the mainform
end;
end;


//in unit2,form2(which is the mainform)
implementation
uses unit1;
{$R *.dfm}
procedure TForm2.Button1Click(Sender: TObject);
begin
form1.Close; //if you want to close all
end;
procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
form1.Close; //if you want to close all
end;
procedure TForm2.FormShow(Sender: TObject);
begin
form1.Hide; //hide the login name form
end;
Avatar of delphibeginner

ASKER

Thanks for all your replies,

This is the source code I use, (I also use a splash screen at startup).

For entering the Name in the firstscreen works, so when I entered a name it's being saved in a file, then I go to the main app, but when I close the main app and start it again, the loginform (firstscreen) shows again, but this shouldn't be happening.

Thanks
program songlisteditor;

uses
  Forms,
  songlisteditor1 in 'songlisteditor1.pas' {Form1},
  ABOUT in 'ABOUT.pas' {AboutBox},
  repunit2 in 'repunit2.pas' {Reportfrm},
  songlist1 in 'songlist1.pas' {Form2},
  repunit in 'repunit.pas' {Listfrm},
  mailsonglist1 in 'mailsonglist1.pas' {Form3},
  addressbook1 in 'addressbook1.pas' {Form4},
  uSplash in 'uSplash.pas' {frmSplash},
  addsongtodatabase1 in 'addsongtodatabase1.pas' {Form5},
  addcontacttodatabase1 in 'addcontacttodatabase1.pas' {Form6},
  firstscreen1 in 'firstscreen1.pas' {LoginForm};

{$R *.res}

begin
  Application.CreateForm(TLoginForm, LoginForm);
  LoginForm.ShowModal;
  if LoginForm.UserLoggedon then begin
    LoginForm.Free;
    Application.Initialize;
    RunSplash;
    Application.MainFormOnTaskbar := True;
    Application.Title := 'Songlist Editor';
    Application.CreateForm(TForm1, Form1);
    Application.CreateForm(TAboutBox, AboutBox);
    Application.CreateForm(TReportfrm, Reportfrm);
    Application.CreateForm(TReportfrm, Reportfrm);
    Application.CreateForm(TForm2, Form2);
    Application.CreateForm(TListfrm, Listfrm);
    Application.CreateForm(TForm3, Form3);
    Application.CreateForm(TForm4, Form4);
    Application.CreateForm(TForm5, Form5);
    Application.CreateForm(TForm6, Form6);
    Application.Run;
  end;
end.

Open in new window

LoginForm.ShowModal;
will display the form and wait for a result - always. it should be conditioned by the validity of a previous logon.
I don't know what would be the behaviour if called outside the main events loop (in the Application.Run), but that's clearly not recommended.
Which is why I put the showmodal in the main form onActivate event (which will be called in the run method).

can you post your LoginForm unit so that we can see how you save the data and other functions like UserLoggedon ?
The LoginForm unit is as followed:

Hope you can help.
unit firstscreen1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, AdvEdit, INIFiles;

type
  TLoginForm = class(TForm)
    Label1: TLabel;
    AdvEdit1: TAdvEdit;
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    UserLoggedOn: boolean;
  end;

var
  LoginForm: TLoginForm;

implementation

{$R *.dfm}

procedure TLoginForm.Button1Click(Sender: TObject);
var
  myIniFile : TIniFile;
begin
  myIniFile := TINIFile.Create(ExtractFilePath(Application.EXEName) + 'worshipleaders.ini');
  myIniFile.WriteString('Worshipleaders', 'Name', AdvEdit1.Text);
  myIniFile.Free;
  UserLoggedon := True;
  Close;
end;

end.

Open in new window

It's not really a login (users have just to enter their names)
ok, about ShowModal outside the run loop :
ShowModal have this piece of code
repeat
 Application.HandleMessage;
 if Application.FTerminate then ModalResult := mrCancel else if ModalResult <> 0 then CloseModal;
until ModalResult <> 0;

so it has its own message loop, and therefore will work even if not in the main events loop.
So best solution would be a class function of TLoginForm that does it all
class function TLoginForm.IsLogged:Boolean;
begin
// implement this as you see fit
 Result:=FileExists(FileWhereLoginIsSaved) And LoginIsValidIn(FileWhereLoginIsSaved);
 if Not Result Then 
  begin   
   LoginForm:=TLoginForm.Create(nil);
   Result:=LoginForm.ShowModal=mrOK;
   LoginForm.Free;
  end;
end;

and in project :

begin
 if TLoginForm.IsLogged then // call the class method
  begin
   Application.Initialize;
   RunSplash;
...
   Application.Run;
  end;
end.   

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of Emmanuel PASQUIER
Emmanuel PASQUIER
Flag of France image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
You can also do this:

On Form show :


procedure TForm1.FormCreate(Sender: TObject);
var
  s,k,l,Glo,atext,Zboo : string;
...
Begin
  // Lets say you stored the file in system directory....

  Zboo:="12345"   // This is the right code....



  if FileExists(SysDir+'\password.psw') then
  begin
     AssignFile(myFile, SysDir+'\password.psw');
     Reset(myFile);
     while not Eof(myFile) do
     begin
       ReadLn(myFile, atext);
     end;


    // Now lets check the contents of the file.... 
    // If the code is wrong (from another PC, delete the file)
    // ...and close the application
    
     if atext<>Zboo then
     begin
       CloseFile(myFile);
       DeleteFile(SysDir+'\password.psw');
       Application.Terminate;
     end;
  end; //end if file exists....
  



  // Our file does not exist !
  if not FileExists(SysDir+'\password.psw') then
  begin
     Application.ShowMainForm := false;
     s:='The password here';
     k:='Password input';
     l:='Your ID: Some ID here....'+#10#13
        + 'Please enter password : ';
     r := InputQuery(k,l,s);
   
     if r then
     begin
       if s=Zboo then
        begin
         Application.ShowMainForm := true;
         //Create a file...
         AssignFile(myFile, SysDir+'\password.psw');
         ReWrite(myFile);
         Write(myFile, s);
         CloseFile(myFile);
        end else Application.Terminate;
     end 

     // Cancel pressed...
     else Application.Terminate;
  end;



End;

Open in new window

>but when I close the main app and start it again, the loginform (firstscreen) shows again, but this shouldn't be happening.


Ok, maybe the mainform is not really the mainform, but the loginform was, please check on your program.dpr

and see this link:
http://delphi.about.com/od/delphitips2008/qt/no_main_form.htm
Thanks epasquier,


I tried it, but the loginform is still appearing even if the ini has the name stored.
Thanks, that did the trick I forgot just like you said to put the Application.Initialize at the top. Now it works perfect.

Many thanks again