delphidelphi-4

Program stays running after exit


My program stays running if I click the X in the top right hand corner of the form. This also happens within Delphi 4 and I am then forced to do a Program Reset as it will not recomplie if i don't. Main form code:

unit Unit3;

interface

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

type
  TMainForm = class(TForm)
    NewButton: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    ExitButton: TButton;
    LockButton: TButton;
    SettingsButton: TButton;
    Label1: TLabel;
    TimeLabel: TLabel;
    Timer1: TTimer;
    procedure ExitButtonClick(Sender: TObject);
    procedure LockButtonClick(Sender: TObject);
    procedure SettingsButtonClick(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure NewButtonClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;

implementation

uses Unit2, Unit1, Unit4;

{$R *.DFM}


procedure TMainForm.ExitButtonClick(Sender: TObject);
begin
if MessageBox(0, 'Are you sure you want to quit?', 'Exit Program?', +mb_YesNo +mb_ICONWARNING) = 6 then
Application.Terminate
else
end;

procedure TMainForm.LockButtonClick(Sender: TObject);
begin
MainForm.Hide;
Login.Show;
Login.LockLabel.Visible := true;
end;

procedure TMainForm.SettingsButtonClick(Sender: TObject);
begin
MainForm.Hide;
Settings.Show;
end;

procedure TMainForm.Timer1Timer(Sender: TObject);
begin
TimeLabel.Caption := TimeToStr(time);
end;

procedure TMainForm.NewButtonClick(Sender: TObject);
begin
TransForm.Show;
MainForm.Hide;
end;

end.

Login Form code:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Mask, inifiles, Unit1;

type
  TLogin = class(TForm)
    PassEdit: TMaskEdit;
    LoginButton: TButton;
    PassLabel: TLabel;
    InvisiButton: TButton;
    LockLabel: TLabel;
    procedure PassEditClick(Sender: TObject);
    procedure LoginButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Login: TLogin;
  IniFile : TIniFile;
  appINI : TIniFile;
  Password : string;

implementation

uses Unit3;



{$R *.DFM}

procedure TLogin.PassEditClick(Sender: TObject);
begin
PassEdit.Text := '';
end;

procedure TLogin.LoginButtonClick(Sender: TObject);
begin
if Password = PassEdit.Text then begin
Login.Hide;
MainForm.Show;
LockLabel.Visible := false;
end
else
showmessage('Incorrect Password!')
end;
procedure TLogin.FormCreate(Sender: TObject);
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
Password := appINI.ReadString('Login','Password','');
appINI.Free;
end;

end.

Setting Form Code

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, inifiles;

type

  TSettings = class(TForm)
    SaveButton: TButton;
    AEditA: TEdit;
    AEditB: TEdit;
    SEditB: TEdit;
    PEditB: TEdit;
    PLabelA: TLabel;
    SLabelA: TLabel;
    ALabelA: TLabel;
    PEditA: TEdit;
    SEditA: TEdit;
    BackButton: TButton;
    SettingsLabel: TLabel;
    ALabelB: TLabel;
    SLabelB: TLabel;
    PLabelB: TLabel;
    AReserveLabel: TLabel;
    BReserveLabel: TLabel;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label8: TLabel;
    Label7: TLabel;
    procedure SaveButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure BackButtonClick(Sender: TObject);
    procedure AEditAKeyPress(Sender: TObject; var Key: Char);
    procedure AEditBKeyPress(Sender: TObject; var Key: Char);
    procedure SEditAKeyPress(Sender: TObject; var Key: Char);
    procedure SEditBKeyPress(Sender: TObject; var Key: Char);
    procedure PEditAKeyPress(Sender: TObject; var Key: Char);
    procedure PEditBKeyPress(Sender: TObject; var Key: Char);
    procedure Button1Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Settings: TSettings;
  IniFile : TIniFile;
  appINI : TIniFile;
  APriceA : String;
  SPriceA : String;
  PPriceA : String;
  APriceB : String;
  SPriceB : String;
  PPriceB : String;
  change : boolean;

implementation

uses Unit3, Unit2;


{$R *.DFM}

procedure TSettings.SaveButtonClick(Sender: TObject);
//Save Button
 begin
  appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  APriceA := (AEditA.Text);
  SPriceA := (SEditA.Text);
  PPriceA := (PEditA.Text);
  APriceB := (AEditB.Text);
  SPriceB := (SEditB.Text);
  PPriceB := (PEditB.Text);
  appINI.WriteString('PricesA','Adult',APriceA);
  appINI.WriteString('PricesA','Student',SPriceA);
  appINI.WriteString('PricesA','Pensioner',PPriceA);
  appINI.WriteString('PricesB','Adult',APriceB);
  appINI.WriteString('PricesB','Student',SPriceB);
  appINI.WriteString('PricesB','Pensioner',PPriceB);
  appINI.Free;
  ShowMessage('Settings Saved Successfully!');
  change := false;
 end;

procedure TSettings.FormCreate(Sender: TObject);
//Displays values as the form is created
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
APriceA := appINI.ReadString('PricesA','Adult','');
SPriceA := appINI.ReadString('PricesA','Student','');
PPriceA := appINI.ReadString('PricesA','Pensioner','');
APriceB := appINI.ReadString('PricesB','Adult','');
SPriceB := appINI.ReadString('PricesB','Student','');
PPriceB := appINI.ReadString('PricesB','Pensioner','');
appINI.Free;
AEditA.Text := (APriceA);
SEditA.Text := (SPriceA);
PEditA.Text := (PPriceA);
AEditB.Text := (APriceB);
SEditB.Text := (SPriceB);
PEditB.Text := (PPriceB);
end;

procedure TSettings.BackButtonClick(Sender: TObject);
//Exit Button
begin
if MessageBox(0, 'Are you sure you want to quit?', 'Exit Program?', +mb_YesNo +mb_ICONWARNING) = 6 then begin
if Change = (true) then
begin
if MessageBox(0, 'Save Changes?', 'Save Changes?', +mb_YesNo +mb_ICONWARNING) = 6 then
  begin
  appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  APriceA := (AEditA.Text);
  SPriceA := (SEditA.Text);
  PPriceA := (PEditA.Text);
  APriceB := (AEditB.Text);
  SPriceB := (SEditB.Text);
  PPriceB := (PEditB.Text);
  appINI.WriteString('PricesA','Adult',APriceA);
  appINI.WriteString('PricesA','Student',SPriceA);
  appINI.WriteString('PricesA','Pensioner',PPriceA);
  appINI.WriteString('PricesB','Adult',APriceB);
  appINI.WriteString('PricesB','Student',SPriceB);
  appINI.WriteString('PricesB','Pensioner',PPriceB);
  appINI.Free;
  ShowMessage('Settings Saved Successfully!');
  Settings.Hide;
  MainForm.Show;
  change := false;
  end
else
change := false;
MainForm.Show;
Settings.Hide;
end
else
MainForm.Show;
Settings.Hide;
end
else
end;

procedure TSettings.AEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  change := true;
  s := ('1234567890.'#8); //Add chars you want to allow
  if pos(key,s) =0 then begin
    Key:=#0;
    showmessage('Only Numbers are allowed. Include cents!');
  end;
end;

procedure TSettings.AEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
  s := ('1234567890.'#8); //Add chars you want to allow
  if pos(key,s) =0 then begin
    Key:=#0;
    showmessage('Only Numbers are allowed. Include cents!');
  end;
end;

procedure TSettings.SEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
  s := ('1234567890.'#8); //Add chars you want to allow
  if pos(key,s) =0 then begin
    Key:=#0;
    showmessage('Only Numbers are allowed. Include cents!');
  end;
end;

procedure TSettings.SEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
  s := ('1234567890.'#8); //Add chars you want to allow
  if pos(key,s) =0 then begin
    Key:=#0;
    showmessage('Only Numbers are allowed. Include cents!');
  end;
end;

procedure TSettings.PEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
  s := ('1234567890.'#8); //Add chars you want to allow
  if pos(key,s) =0 then begin
    Key:=#0;
    showmessage('Only Numbers are allowed. Include cents!');
  end;
end;

procedure TSettings.PEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
change := true;
  s := ('1234567890.'#8); //Add chars you want to allow
  if pos(key,s) =0 then begin
    Key:=#0;
    showmessage('Only Numbers are allowed. Include cents!');
  end;
end;
//End of Settings
procedure TSettings.Button1Click(Sender: TObject);
begin

Settings.hide;
end;

end.

Project Data:

program Project1;

uses
  Forms,
  Unit1 in 'Unit1.pas' {Settings},
  Unit2 in 'Unit2.pas' {Login},
  Unit3 in 'Unit3.pas' {MainForm},
  Unit4 in '..\Write to ini\Unit4.pas' {TransForm};


{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TLogin, Login);
  Application.CreateForm(TMainForm, MainForm);
  Application.CreateForm(TSettings, Settings);
  Application.Run;
end.

When i close the application it stays running, can you help me fix this?


Solution

  • As David said, your TLogin form is being set as Application.MainForm because it is the first form create by Application.CreateForm(). You are simply hiding the TLogin form, not closing it, which is why your app does not fully exit. When you close the TMainForm form, the TLogin form is still running.

    Given the code you have shown, your TMainForm form should be the only one created with Application.CreateForm(). All of your other forms should be created on an as-needed basis instead.

    You have also coded Unit1, Unit2, and Unit3 (what is Unit4?) to be inter-dependant on each other when they do not need to be, so you should remove that dependancy as well. The TLogin and TSettings units should be standalone units.

    Try something more like this instead:

    Main form:

    unit Unit3; 
    
    interface 
    
    uses 
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
      StdCtrls, ExtCtrls; 
    
    type 
      TMainForm = class(TForm) 
        NewButton: TButton; 
        Button2: TButton; 
        Button3: TButton; 
        Button4: TButton; 
        Button5: TButton; 
        Button6: TButton; 
        ExitButton: TButton; 
        LockButton: TButton; 
        SettingsButton: TButton; 
        Label1: TLabel; 
        TimeLabel: TLabel; 
        Timer1: TTimer; 
        procedure FormCreate(Sender: TObject);
        procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
        procedure ExitButtonClick(Sender: TObject); 
        procedure LockButtonClick(Sender: TObject); 
        procedure SettingsButtonClick(Sender: TObject); 
        procedure Timer1Timer(Sender: TObject); 
        procedure NewButtonClick(Sender: TObject); 
      protected
        procedure WndProc(var Message: TMessage); override;
      private 
        { Private declarations } 
      public 
        { Public declarations } 
      end; 
    
    var 
      MainForm: TMainForm; 
    
    implementation 
    
    uses
      Unit2, Unit1, Unit4; 
    
    {$R *.DFM} 
    
    const
      WM_LOCK = WM_USER + 100;
    
    procedure TMainForm.FormCreate(Sender: TObject);
    begin 
      PostMessage(Handle, WM_LOCK, 0, 0);
    end;
    
    procedure TMainForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean); 
    begin
      if Application.MessageBox('Are you sure you want to quit?', 'Exit Program?', MB_YESNO or MB_ICONWARNING) <> IDYES then
        CanClose := False;
    end;
    
    procedure TMainForm.WndProc(var Message: TMessage);
    begin
      if Message.Msg = WM_LOCK then
        LockButtonClick(nil)
      else
        inherited; 
    end;
    
    procedure TMainForm.ExitButtonClick(Sender: TObject); 
    begin 
      Close;
    end; 
    
    procedure TMainForm.LockButtonClick(Sender: TObject); 
    var
      Login: TLogin;
    begin 
      Login := TLogin.Create(nil);
      try
        Hide; 
        Login.LockLabel.Visible := True; 
        if Login.ShowModal = mrOk then 
          Show
        else
          Application.Terminate; 
      finally
        Login.Free; 
      end;
    end; 
    
    procedure TMainForm.SettingsButtonClick(Sender: TObject); 
    var
      Settings: TSettings;
    begin 
      Settings := TSettings.Create(nil);
      try 
        Settings.ShowModal; 
      finally
        Settings.Free; 
      end;
    end; 
    
    procedure TMainForm.Timer1Timer(Sender: TObject); 
    begin 
      TimeLabel.Caption := TimeToStr(time); 
    end; 
    
    procedure TMainForm.NewButtonClick(Sender: TObject); 
    begin 
      TransForm.Show; 
      Hide; 
    end; 
    
    end. 
    

    Login form:

    unit Unit2; 
    
    interface 
    
    uses 
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
      StdCtrls, Mask; 
    
    type 
      TLogin = class(TForm) 
        PassEdit: TMaskEdit; 
        LoginButton: TButton; 
        PassLabel: TLabel; 
        InvisiButton: TButton; 
        LockLabel: TLabel; 
        procedure PassEditClick(Sender: TObject); 
        procedure LoginButtonClick(Sender: TObject); 
        procedure FormCreate(Sender: TObject); 
      private 
        { Private declarations } 
      public 
        { Public declarations } 
      end; 
    
    implementation 
    
    uses
      inifiles; 
    
    var 
      Password : string; 
    
    {$R *.DFM} 
    
    procedure TLogin.FormCreate(Sender: TObject); 
    var
      appINI : TIniFile; 
    begin 
      appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini')); 
      try
        Password := appINI.ReadString('Login','Password',''); 
      finally
        appINI.Free; 
      end;
    end; 
    
    procedure TLogin.PassEditClick(Sender: TObject); 
    begin 
      PassEdit.Text := ''; 
    end; 
    
    procedure TLogin.LoginButtonClick(Sender: TObject); 
    begin 
      if Password <> PassEdit.Text then
      begin 
        ShowMessage('Incorrect Password!') 
        Exit;
      end;
      LockLabel.Visible := False; 
      ModalResult = mrOk;
    end; 
    
    end. 
    

    Settings Form:

    unit Unit1; 
    
    interface 
    
    uses 
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, 
      StdCtrls; 
    
    type 
      TSettings = class(TForm) 
        SaveButton: TButton; 
        AEditA: TEdit; 
        AEditB: TEdit; 
        SEditB: TEdit; 
        PEditB: TEdit; 
        PLabelA: TLabel; 
        SLabelA: TLabel; 
        ALabelA: TLabel; 
        PEditA: TEdit; 
        SEditA: TEdit; 
        BackButton: TButton; 
        SettingsLabel: TLabel; 
        ALabelB: TLabel; 
        SLabelB: TLabel; 
        PLabelB: TLabel; 
        AReserveLabel: TLabel; 
        BReserveLabel: TLabel; 
        Label1: TLabel; 
        Label2: TLabel; 
        Label3: TLabel; 
        Label4: TLabel; 
        Label5: TLabel; 
        Label6: TLabel; 
        Label8: TLabel; 
        Label7: TLabel; 
        procedure SaveButtonClick(Sender: TObject); 
        procedure FormCreate(Sender: TObject); 
        procedure BackButtonClick(Sender: TObject); 
        procedure Button1Click(Sender: TObject); 
      private 
        { Private declarations } 
        function Changed: Boolean;
        function SaveSettings: Boolean;
      public 
        { Public declarations } 
      end; 
    
    var 
      APriceA : String; 
      SPriceA : String; 
      PPriceA : String; 
      APriceB : String; 
      SPriceB : String; 
      PPriceB : String; 
    
    implementation 
    
    uses
      inifiles; 
    
    {$R *.DFM} 
    
    procedure LoadSettings;
    var
      appINI: TIniFile; 
    begin
      appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini')); 
      try
        APriceA := appINI.ReadString('PricesA','Adult',''); 
        SPriceA := appINI.ReadString('PricesA','Student',''); 
        PPriceA := appINI.ReadString('PricesA','Pensioner',''); 
        APriceB := appINI.ReadString('PricesB','Adult',''); 
        SPriceB := appINI.ReadString('PricesB','Student',''); 
        PPriceB := appINI.ReadString('PricesB','Pensioner',''); 
      finally
        appINI.Free; 
      end;
    end;
    
    procedure TSettings.FormCreate(Sender: TObject); 
    begin 
      AEditA.Text := APriceA; 
      AEditA.Modified := False; 
      SEditA.Text := SPriceA; 
      SEditA.Modified := False; 
      PEditA.Text := PPriceA; 
      PEditA.Modified := False; 
      AEditB.Text := APriceB; 
      AEditB.Modified := False; 
      SEditB.Text := SPriceB; 
      SEditB.Modified := False; 
      PEditB.Text := PPriceB; 
      PEditB.Modified := False; 
    end; 
    
    function TSettings.Changed: Boolean;
    begin
      Result := AEditA.Modified or 
                SEditA.Modified or
                PEditA.Modified or
                AEditB.Modified or
                SEditB.Modified or
                PEditB.Modified; 
    end;
    
    function TSettings.SaveSettings: Boolean;
    var
      dbl: Double;
    begin
      Result := TryStrToFloat(AEditA.Text, dbl) and
                TryStrToFloat(SEditA.Text, dbl) and
                TryStrToFloat(PEditA.Text, dbl) and 
                TryStrToFloat(AEditB.Text, dbl) and 
                TryStrToFloat(SEditB.Text, dbl) and 
                TryStrToFloat(PEditB.Text, dbl);
    
      if not Result then
      begin
        ShowMessage('Only Numbers are allowed. Include cents!'); 
        Exit;
      end;
    
      APriceA := AEditA.Text; 
      SPriceA := SEditA.Text;
      PPriceA := PEditA.Text; 
      APriceB := AEditB.Text; 
      SPriceB := SEditB.Text; 
      PPriceB := PEditB.Text; 
    
      appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini')); 
      try
        appINI.WriteString('PricesA','Adult',APriceA); 
        appINI.WriteString('PricesA','Student',SPriceA); 
        appINI.WriteString('PricesA','Pensioner',PPriceA); 
        appINI.WriteString('PricesB','Adult',APriceB); 
        appINI.WriteString('PricesB','Student',SPriceB); 
        appINI.WriteString('PricesB','Pensioner',PPriceB); 
      finally
        appINI.Free; 
      end;
    
      AEditA.Modified := False; 
      SEditA.Modified := False;
      PEditA.Modified := False; 
      AEditB.Modified := False; 
      SEditB.Modified := False; 
      PEditB.Modified := False; 
    
      ShowMessage('Settings Saved Successfully!');
      Result := True;
    end;
    
    procedure TSettings.SaveButtonClick(Sender: TObject); 
    begin 
      SaveSettings;
    end; 
    
    procedure TSettings.BackButtonClick(Sender: TObject); 
    begin 
      if Changed then 
      begin 
        if Application.MessageBox('Save Changes?', 'Save Changes?', MB_YESNO or MB_ICONWARNING) = IDYES then
        begin
          if not SaveSettings then
            Exit;
        end;
      end;
      ModalResult = mrOk; 
    end; 
    
    procedure TSettings.Button1Click(Sender: TObject); 
    begin 
      Close; 
    end; 
    
    initialization
      LoadSettings;
    
    end. 
    

    Project:

    program Project1; 
    
    uses 
      Forms, 
      Unit1 in 'Unit1.pas' {Settings}, 
      Unit2 in 'Unit2.pas' {Login}, 
      Unit3 in 'Unit3.pas' {MainForm}, 
      Unit4 in '..\Write to ini\Unit4.pas' {TransForm}; 
    
    
    {$R *.RES} 
    
    begin 
      Application.Initialize; 
      Application.CreateForm(TMainForm, MainForm); 
      Application.ShowMainForm := False;
      Application.Run; 
    end.