Thersippos
Thersippos

Reputation: 27

Delphi: refer to a component from multiple frames

I want to refer to a component (using loop) which exists in multiple frames. The component is the same for all frames.

So, I am currently using: Tfrm1(FindComponent('page_'+i)).comboBoxAccount

Which means I use FindComponent with i in a loop to access all comboBoxAccount in all TabSheets.

The problem is that I have to use casting to make Delphi understand which component I want to access, so I've put Tfrm1( ) in front of FindComponent.

So, if I want to use casting with a loop what can I do?

I could just use:

Tfrm1(FindComponent('page_'+i)).comboBoxAccount
Tfrm2(FindComponent('page_'+i)).comboBoxAccount
Tfrm3(FindComponent('page_'+i)).comboBoxAccount

but is there a way to loop Tfrm without writing them one by one?

Upvotes: 0

Views: 1268

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596582

page_1, page_2, etc are TabSheets, not frames, but you are casting them to frames, which is wrong.

If each frame has multiple TabSheets on it, and each TabSheet has a ComboBox on it, you would not use FindComponent() at all. You would have to iterate through parent/child Controls[] lists instead, or use FindChildControl().

However, if the frame is the Owner of the ComboBox (which it would be if the ComboBox is added to the frame at design-time), then you would use FindComponent() on the frame itself. But you cannot have multiple child components with the same name, so each ComboBox on each TabSheet would need a unique name:

cb := TComboBox(frm1.FindComponent('comboBoxAccount_'+IntToStr(i)));

Repeating for each index of frm1, then all indexes of frm2, then frm3.

If your ComboBox really is named just comboBoxAccount then I wonder if you really have one parent container that has multiple TabSheets on it, and each TabSheet has a frame on it, and each frame has only one ComboBox named comboBoxAccount on it. If that is the case, you don't need to do any searching at all, just use your existing object pointers directly:

cb :=  frm1.comboBoxAccount;
cb :=  frm2.comboBoxAccount;
cb :=  frm3.comboBoxAccount;

But if you really want to use a loop, then put the frames into a list, eg:

private
    Frames: TList;

...

Frames := TList.Create;
Frames.Add(frm1);
Frames.Add(frm2);
Frames.Add(frm3);

...

for I := 0 to Frames.Count-1 do
begin
  // assuming TFrm1, TFrm2, etc do not have a common ancestor holding the ComboBox...
  cb := TComboBox(TWinControl(Frames[i]).FindComponent('comboBoxAccount'));
  ...
end;

Or use an array:

private
  // assuming TFrm1, TFrm2, etc do not have a common ancestor holding the ComboBox...
  Frames: array[0..2] of TWinControl;

...

Frames[0] := frm1;
Frames[1] := frm2;
Frames[2] := frm3;

...

for I := Low(Frames) to High(Frames) do
begin
  cb := TComboBox(Frames[i].FindComponent('comboBoxAccount'));
  ...
end;

Update: given new information you provided, you can find the ComboBox like this instead:

cb := Tfrm1(PageControl[i].Pages[j].FindChildControl('frame_'+IntToStr(i))).comboBoxAccount;

Your while loop is creating multiple tabsheets and frames that have the same Name, which is not valid. I would suggest not naming them at all.

while condition=true do
begin
  TabSheet := TTabSheet.Create(PageControl[i]);
  TabSheet.Caption := '';
  //TabSheet.Name:='tabesheet_'+IntToStr(i);
  TabSheet.PageControl := PageControl[i];
  TabSheet.PageControl.ActivePageIndex:=0;
  {I also create a frame for each TabSheet. In every frame there is the     ComboBox that I want to access}
  frame := Tfrm1.Create(TabSheet);
  //frame.Name:='frame_'+IntToStr(i);
  frame.Parent:=TabSheet;
end;

Assuming a frame is the only child of its TabSheet, you can then do this:

cb := Tfrm1(PageControl[i].Pages[j].Controls[0]).comboBoxAccount;

Upvotes: 1

Related Questions