Home > front end >  An access violation that occurred trying to open another form
An access violation that occurred trying to open another form

Time:10-24

I am having an Access Violation when my project tries to open up a separate form using the .Show command.

The code is supposed to open the login form. But just outputs an Access Violation error.

This is the code from the main form, and is run on its activation:

procedure TForm4.FormActivate(Sender: TObject);
begin
  label1.BringToFront;
  DBMatch.Enabled := false;
  DBContestants.Enabled := false;
  btncreate.Enabled := false;
  DbNav.Enabled := false;
  login.Show;
end;

The below code is the start of the login form:

unit login_form;

interface

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

type
  Tlogin = class(TForm)
    edit_username: TEdit;
    edit_password: TEdit;
    btnlogin: TButton;
    btnForgotten: TButton;
    lUsername: TLabel;
    LPassword: TLabel;
    Imageside: TImage;
    procedure btnloginClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  private
    { Private declarations }
  public
  end;

var
  login: Tlogin;
  password,result:string;

implementation
{$R *.dfm}
 uses dmChess_u;

This is one of the errors on the main form

Images of the main file for the program

CodePudding user response:

Your Form4 (MainForm) object is being created before the login object is created. Chances are, the TForm.OnActivate event is also being fired before the login object is created, too. Thus, the login pointer would still be nil when you try to call Show on it. You can easily verify that by using the debugger.

A Form's OnActivate event is not a good place to display a login form. That event is fired whenever a Form gains input focus, which can happen many times during the Form's lifetime.

Also, it is generally best to not auto-create your Form objects at program startup, except for the MainForm. Create your Form objects dynamically via their Create constructor only when actually needed, and free them when no longer needed, eg:

login := Tlogin.Create(nil);
try
  login.ShowModal;
finally
  login.Free;
end;

Alternatively:

login := Tlogin.Create(Self);
login.Show;

...

// OnClose event handler
procedure TloginClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;

However, in this particular case, if you want the user to login before interacting with the MainForm, I would suggest displaying the login form before the MainForm is even created, eg:

Application.Initialize;

login := Tlogin.Create(nil);
try
  if login.ShowModal <> mrOk then
    Exit;
finally
  login.Free;
end;

Application.CreateForm(TForm4, Form4);
Application.Run;

CodePudding user response:

The other answer is really good. I will just add to one of the points. Don't create the form manually. Just create it in the project and then call it when needed. After you've created the form in your project you can do whatever you want on the form interface and code what you need. Then when you need the form, you can have a button on the main form. When the button is clicked make it show the form.

frmLogin.ShowModal;

Make that button invisible. Add this code to your mainForm on create code block, or just manually do it on the button properties by unchecking the visible property.

btnLogin.Visible := false;

Then go to your main form events and go to On Show. Double click and in the code block that appears just write

btnLogin.Click;

This means that before the form shows it will click the existing button. Since the show event is executed after the create event and you already have both forms created in the project, you won't have that problem.

  • Related