In your question you left out a very important piece of the puzzle. You’ve mentioned it in comments, but I repeat it here because it’s the direct trigger of your problem. In comments you said the form is created as follows:
with TForm1.Create(Self) do
begin
try
ShowModal;
finally
Free;
end;
end;
Your problem is that within the call-chain of ShowModal
you expect Form1
to be assigned specifically to the instance you’ve just created. But clearly you haven’t yet done anything to set Form1
.
Your “solution” was to assign Form1
within the ShowModal
call-chain. While this solves your immediate problem, it is far from correct, and I’ll explain why later. First I’ll show the simple solution that would have avoided the problem altogether (note it’s not a complete solution because there are far more problems with your code than you realise).
Solution, get rid of with:
//This first line is the most important.
//It explicitly sets which variable must be assigned to the new form.
Form1 := TForm1.Create(Self);
try
Form1.ShowModal;
finally
Form1.Free;
end;
Vishal, try it out. If you do, you’ll see it works. And hopefully I have your full attention now. You didn’t believe at first, but perhaps you now realise I really do understand correctly.
So why do I say your “solution” wrong? After all it seems to solve the problem….
Well, you said it yourself: you expected
Form1
to be assigned at the start ofFormShow
. You’re right, it should be. By assigningForm1 := Self;
insideFormShow
you’re just patching up the earlier mistake. Surely you agree it’s better to fix the original mistake than to just patch over it later?
But there’s a deeper problem here… I’m not sure you understand the difference between “object instances” and “classes”. (If you do, then please still read the next few paragraphs for revision.)
It seems you expected that when TForm1
was created it should be automatically assigned to the Form1
variable. It’s as if you expected there would only ever be one TForm1
in memory at any point in time. But TForm1
is a class type; meaning it generally defines the behaviour for any number of object instances of the same type. Each time you create a TForm1
, it’s a new separate instance of the form. And each instance can have its own variable that is assigned to it. E.g.
JohnsForm1 := TForm1.Create(Self);
PaulsForm1 := TForm1.Create(Self);
Consider for a moment what happens with your incorrect “solution” if you needed 2 form variable? What would you write inside the FormShow
method? JohnsForm1 := Self;
or PaulsForm1 := Self;
?
Of course you can still choose to keep only 1 instance of TForm1
in memory at a time. But Delphi has no way to automatically know that is what you intend. So you should still do any desired assignments explicitly as above.
I mentioned there are still more serious problems with your code. It’s related to the above discussion about object instance and class types.
Your TTest
class makes a bunch of unnecessary assumptions:
- It assumes there will only ever be 1 instance of
TForm1
. - It assumes the form will always be available when needed.
- And it assumes the form will be assigned to the
Form1
variable.
So again, if you need a JohnsForm1
and a PaulsForm1
, your code won’t work.
A tiny change to TTest.LoadMyData
and TForm1.FormShow
solves these problems.
//Write LoadMyData so it can be told which form instance to load the data into
procedure TTest.LoadMyData(ALoadForm: TForm1);
begin
ALoadForm.LoadData;
end;
//Change FormShow to tell Test which form to use in LoadMyData
procedure TForm1.FormShow(Sender: TObject);
begin
Initilize;
Test := TTest.Create;
Test.LoadMyData(Self);
end;
For the record, David already gave you this information in his answer. His answer also demonstrates the proper resource protection for the new TTest
instance, whereas I’ve left it out for the sake of simplicity.
By the way, these 2 little changes would have also solved your problem.
Basically, you had 2 mistakes in your code. The combination of both mistakes caused your problem.
You can fix either one to make the problem go away. But you should fix both to make your code better.
6
solved Access Violation While Calling Form’s Method