Open and close vcl form
Right now i have 2 forms. On Form1 i open up Form2 like this:
procedure TForm1.Action1Execute(Sender: TObject);
var
Form2: TForm2;
begin
Form2 := TForm2.Create(Form2);
Form2.ShowModal;
Form2.Free;
end;
Now i want to close the Form2 with a button on it. So i tried
procedure TForm2.cancelBtnClick(Sender: TObject);
begin
Form2.Close;
end;`
B开发者_开发知识库ut that only gives me Access violation error when i click that button. What i am doing wrong?
The normal way to do this is to do
procedure TForm1.Action1Execute(Sender: TObject);
begin
with TForm2.Create(nil) do
try
ShowModal;
finally
Free;
end;
end;
and, if TForm2
contains a OK button, this should have the ModalResult
property set to mrOK
at design-time. Use the object inspector to set this. You probably also want to set Default
to True
. Now you can 'click' the OK button by pressing the Enter key on your keyboard!
In addition, if there is a Cancel button in the dialog, this should have ModalResult
set to mrCancel
and Cancel
set to True
. Now you can 'click' the Cancel button by pressing the Escape key on your keyboard!
A button with a ModalResult
value will automatically close a modal dialog box.
Since the form is showing modally the correct solution is to set ModalResult := mrCancel
in your button click handler. The shortcut is to set the ModalResult
property of the button to mrCancel
and then you don't even need the event handler.
Note that your form is being created incorrectly. You are passing the unassigned variable Form2
as the Owner
parameter to the constructor. I expect this is the cause of the access violation.
You should pass another form, Application
or nil
, for example. In fact in this case you may as well pass nil so that the code should read:
Form2 := TForm2.Create(nil);
try
Form2.ShowModal;
finally
Form2.Free;
end;
If you pass an owner then the form will be destroyed when the owner is destroyed. Since you are destroying it yourself, you don't need to pass an owner.
That said, it is sometimes useful to set the owner, for example if you are using one of the Position
property values that sets the form's position based on the owner's position. If so then I recommend passing Self
in this instance which is a TForm1
object reference.
The other two answers discuss other ways to solve your problem.
I am going to point out the cause of the problem.
You have two variables named Form2. One contains the form and the other is uninitialized most likely Nil. The cause of the A/V is because your accessing the Nil variable.
When working with in a class you should avoid using the variable name of the class instead you can reference it's members directly such as calling Close;
without referencing the variable. To keep things clear you can also prefix it with self.
so replace form2.close;
with self.close;
In your second code, you're already in form 2, so you would only need to do
procedure TForm2.cancelBtnClick(Sender: TObject);
begin
Close;
end;
If in your first code you created a variable you didnt use the generic Form2 variable made as a public variable in the form, its not then allocated to the form you called. So it will give errors. If at the top of the unit, you removed the "var Form2: TForm2;" line, you'd see it complain about the lack of variable for that line, change it to close, it will go away and so will your error.
I don't know if you already resolved that question or created a new code to avoid the problem, but what I think is happening (and you didn't showed all your code to confirm) is that you created bad code on the OnActivate main form event.
When you exit the second form, you return to your mainform and it "actvates" again. Probably you manipulated an object that do not exists anymore.
精彩评论