Reputation: 111
I am writing an application like this:
There is a main form with a PageControl on it, In the Page Control I create Tabsheets, In the Tabsheets, forms are placed.
This helps because the user can create one type of form more than once, like a standard pdf viewer opened in more than one tab, but displaying different data, in essence its the same form.
This works very well and is very useful! Unfortunately something important isn't working, this is the problem:
This code will work fine:
procedure TForm1.Button1Click(Sender: TObject);
begin
Label1.Caption := 'Hello';
end;
The caption will change, however, if I would like to call a method instead, like this:
Procedure changeLabel(str : String);
Begin
Form1.Label1.Caption := str;
End;
procedure TForm1.Button1Click(Sender: TObject);
begin
changeLabel('Hello');
end;
I get an access violation at Form1.Label1.Caption := str; in the procedure
Here is how I created the form:
procedure TfrmPage.CDMA1Click(Sender: TObject);
var
TabSheet: TTabSheet;
frmTest : TForm;
begin
TabSheet := TTabSheet.Create(PageControl1);
TabSheet.Caption := 'kjklhhj';
TabSheet.PageControl := PageControl1;
frmTest := TForm1.Create(Nil);
frmTest.Show;
frmTest.Parent := TabSheet;
end;
I did everything as everyone said here: another stackoverflow question
My Question, how can the newly created form, pinned to the Tabsheet, access its own procedures without throwing exceptions? Another piece that might be important: When I have delphi Auto-Create the form, theres no access violation but the method does nothing to the form, so I think the procedure might be changing things on the wrong form, one thats not created yet (which gives AV), and not to the one i just created, or the application is not calling the method on my new form, but calling one somewhere where that form isn't created yet.
If I auto-create the form, calling the procedure probably changes the label on the form that was created when the application started and not the new form..
Any help would be appreciated, as I've been googling for hours now with no real help to this problem
Thanks in advance :)
Upvotes: 0
Views: 992
Reputation: 21033
If you plan to create several instances of the TForm1
class, it is correct to not auto-create Form1
. In fact you should delete the Form1: TForm1
declaration altogether to reduce the risk of errors.
You probably want to keep references to the forms you create f.ex. in a TList
, possibly hosted by the TfrmPage
instance depending on what TfrmPage
is. (See below in discussion about AV)
Access Violation
When you created an instance of TForm1
in TfrmPage.CDMAClick()
you assigned the reference of the created form to a local variable frmTest
and then you show it in a tabsheet. You can click Button1
and change caption of Label1
. However when you call the ChangeLabel
procedure you state
Form1.Label1.Caption := str;
but the Form1
variable has never been assigned, therefore is nil
and the AV is triggered. Now, since you assigned the forms reference to the local frmTest
variable in TfrmPage.CDMAClick()
you don't really have any reference anymore to the form, and cannot access it (actually, since you parented it to the tabsheet, you can search for it in the tabsheets controls). This is why I suggested to keep references to the forms you create in a list. Then you can access the forms through that list when needed.
My Question, how can the newly created form, pinned to the Tabsheet, access its own procedures without throwing exceptions?
You can always access an objects methods, fields and properties from the object itself without using a reference variable. In fact, you should never use the objects reference variable from within the object:
Label1.Caption := 'Whatever'; // correct from within the form
Sometimes it may be necessary to use a reference within the object and for that purpose you can use self
f.ex.:
self.Label1.Caption := 'Whatever'; // self can be used if needed
From an external method/procedure/function you need to use a reference to the object
Form1.Label1.Caption := 'Whatever'; // assuming Form1 has been assigned
Upvotes: 1