Program stays running after exit

4.5k views Asked by At

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?

2

There are 2 answers

0
Remy Lebeau On BEST ANSWER

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. 
3
Arno Botha On

The easiest way to to this would be to be in a close button with just one line of code:

BtnClose.click
Begin
  Application.terminate;
End;

Hope that helps