Program Errors when trying to change forms

2019-08-27 11:29发布

问题:

I firstly created a form that will show settings. Then i created a login box that will load a password from an ini file. I originally thought that it was an error with loading the ini file. Though I have isolated it to when I load the settings form. Here is the code for all of them.

The code for the settings screen:

    unit Unit1;

interface

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

type

  TForm1 = class(TForm)
    SaveButton: TButton;
    AEditA: TEdit;
    AEditB: TEdit;
    SEditB: TEdit;
    PEditB: TEdit;
    PLabelA: TLabel;
    SLabelA: TLabel;
    ALabelA: TLabel;
    PEditA: TEdit;
    SEditA: TEdit;
    ExitButton: TButton;
    Settings: 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 ExitButtonClick(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);

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

var
  Form1: TForm1;
  IniFile : TIniFile;
  appINI : TIniFile;
  APriceA : String;
  SPriceA : String;
  PPriceA : String;
  APriceB : String;
  SPriceB : String;
  PPriceB : String;

implementation


{$R *.DFM}

procedure TForm1.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!');
 end;

procedure TForm1.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 TForm1.ExitButtonClick(Sender: TObject);
//Exit Button
begin
Close;
end;

procedure TForm1.AEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  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 TForm1.AEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  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 TForm1.SEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  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 TForm1.SEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  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 TForm1.PEditAKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  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 TForm1.PEditBKeyPress(Sender: TObject; var Key: Char);
var s:string;
begin
  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
end.

The code for the login form:

unit Unit2;

interface

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

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

var
  Form2: TForm2;
  IniFile : TIniFile;
  appINI : TIniFile;
  Password : string;

implementation



{$R *.DFM}

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

procedure TForm2.LoginButtonClick(Sender: TObject);
begin
//if Password = PassEdit.Text then begin
Form2.Hide;
showmessage('test');
Form1.Show;
end;
//end;
procedure TForm2.FormCreate(Sender: TObject);
begin
appINI := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
Password := appINI.ReadString('Login','Password','');
ShowMessage(Password);
appINI.Free;
end;

end.

This is the project:

program Project1;

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


{$R *.RES}

begin
  Application.Initialize;
  //Application.CreateForm(TForm1, Form1);
  Application.CreateForm(TForm2, Form2);
  Application.Run;
end.

回答1:

You've commented out the line of code in the .dpr file that createsForm1`:

  //Application.CreateForm(TForm1, Form1);

But you're accessing that uncreated form in Unit1:

procedure TForm2.LoginButtonClick(Sender: TObject);
begin
//if Password = PassEdit.Text then begin
Form2.Hide;
showmessage('test');
Form1.Show;        // <-- Accessing uncreated form here
end;

Uncomment the line in the project file so it gets created. Note that the first form that's created with Application.CreateForm becomes your application's main form, and when that form is closed your application terminates.

You also have another major flaw in your code. You should never reference the form itself by name from within one of it's own methods, like you do here from within TForm2.LoginButtonClick:

    Form2.Hide;

This means that if you ever rename the form, it won't compile, and if you create more than one TForm2, your code will either access the wrong one or will cause access violations for accessing a non-created form (like the problem you're having now). You should either just use the form's method directly, like Hide;' from the method, or useSelf.Hide;` to refer to the instance currently running the method.

(For future reference: When you have a problem, it helps if you explain what that problem is when you ask for help solving it. "Program errors" with no other information about the error is meaningless by itself. When you type "error", the very next thing you should add is the exact error you're having, including the exact error message including any address information. We can't see your screen from where we sit, so we only have the info you provide us to go by in helping you.)