Link to home
Start Free TrialLog in
Avatar of chrisbray
chrisbrayFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Accessing Dynamically Created Components At Runtime

I have created some tabsheets at runtime, and created ListBoxes to go with them:

      // Does the Tab Exist?
      TabFound := False;
      if Length(TabName) > 0 then
        begin
          for j := 0 to PageControl1.PageCount - 1 do
            begin
              if PageControl1.Pages[j].Caption = TabName then
                begin
                  TabFound := True;
                  Break;
                end;
            end;
          if not TabFound then
            begin
              // Add Tab
              with TTabSheet.Create(PageControl1) do
                begin
                  PageControl := PageControl1;
                  TabVisible := True;
                  Caption := TabName;
                  // Add the ListBox
                  with TListBox.Create(PageControl1.Pages[PageControl1.PageCount -1]) do
                    begin
                      Parent := PageControl1.Pages[PageControl1.PageCount -1];
                      Top := 24;
                      Left := 16;
                      Width := 641;
                      Height := 297;
                      Name := StripSpaces(TabName)+'ListBox';
                      OnMouseUp := ProgramListBoxMouseUp;
                    end;
                end;
             end;
        end;

I then need to access the individual list boxes to add items to them.   If I use FindComponent or iterate through the component list it doesn't find any listboxes at all, not even the one created at design time:

      // Load into the List Box
      if TabName = '' then
        ProgramListBox.Items.AddObject(DisplayText, p)
      else
        begin
          ListBoxName := StripSpaces(TabName)+'ListBox';
          // Test code to see if listboxes being found
          for j := 0 to ComponentCount-1 do
            begin
              Temp := Components[i];
              if Temp is TListBox then
                ShowMessage(TListBox(Temp).Name);  // This never fires, therefore no list boxes?
            end;
          // This should have found it and done the job!!
          ListBox := TListBox(FindComponent(ListBoxName));
          if ListBox <> NIL then
            ListBox.Items.AddObject(DisplayText, p)
          else
            ShowMessage('Not Found');
        end;
    end;

Obviously I am missing something damn silly - anyone got any ideas?
Avatar of chrisbray
chrisbray
Flag of United Kingdom of Great Britain and Northern Ireland image

ASKER

Typo in there - i instead of j:

     // Load into the List Box
      if TabName = '' then
        ProgramListBox.Items.AddObject(DisplayText, p)
      else
        begin
          ListBoxName := StripSpaces(TabName)+'ListBox';
          // Test code to see if listboxes being found
          for j := 0 to ComponentCount-1 do
            begin
              Temp := Components[j];
              if Temp is TListBox then
                ShowMessage(TListBox(Temp).Name);  // This never fires, therefore no list boxes?
            end;
          // This should have found it and done the job!!
          ListBox := TListBox(FindComponent(ListBoxName));
          if ListBox <> NIL then
            ListBox.Items.AddObject(DisplayText, p)
          else
            ShowMessage('Not Found');
        end;
    end;

Still doesn't work, though!!

Chris Bray.
Try this:

unit Unit1_Q_21485950;

interface

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

type
  TForm1 = class(TForm)
    PageControl1: TPageControl;
    Panel1: TPanel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    private
    { Private declarations }
    public
      ListBox:  TListBox;
      function  TabSheet_Exists(SName: string): Boolean;
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
  I:      Integer;
begin
  with PageControl1 do
  begin
    for I := 0 to 9 do
    begin
      with TTabSheet.Create(Self) do
      begin
        PageControl := PageControl1;
        TabVisible := (PageIndex mod 2 = 0);
        Caption := 'PageIndex: ' + IntToStr(PageIndex) + '  TabIndex: ' + IntToStr(TabIndex);
        Name := 'TabSheet' + IntToStr(I);
      end;
    end;
    ListBox := TListBox.Create(Self);
    ListBox.Parent := PageControl1.Pages[0];
    ListBox.Height := 400;
    ListBox.Width := 600;
  end;
end;

function  TForm1.TabSheet_Exists(SName: string): Boolean;
var
  I:      Integer;
begin
  Result := False;
  for I := 0 to ComponentCount-1 do
  begin
    if (Components[I] is TTabSheet) then
    begin
      if ((Components[I] as TTabSheet).Name=SName) then
      begin
        Result := True;
        Break;
      end;  
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  I:      Integer;
  S:      string;
begin
  ListBox.Clear;
  for I := 0 to 9 do
  begin
    S := 'TabSheet' + IntToStr(I);
    if TabSheet_Exists(S) then
      ListBox.Items.Add(S);
  end;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  ListBox.Free;
end;

end.
download above example from:
page:        http://www.geocities.com/esoftbg/
  link:        Q_21485950.zip        Accessing Dynamically Created Components At Runtime
I am very sorry to say that your response is no help whatsoever...  my code can already do all that and more!

The problem is after I create listboxes on the internal dynamically created pages.  The reason this is a problem is that despite giving them a name which can be confirmed as given using a simple piece of test code FindComponent does not find them, and iterating through the list of components does not report ANY TListBoxes - not even the one that is created at designtime on the initial tabsheet.

Whilst I am sure that this is something stupid I am doing (or not doing) I would be very grateful to find out what it is!

To look at your example, I might need to create a listbox on TabSheet3, call it ListBox3,  and add something to it.  I need to be able to do ListBox3.Items.Add('ThisString') or whatever... but without pre-coding it.

Chris Bray.
Here is another example that perhaps shows the problem more effectively.  The following procedure is assigned to all the Listboxes as part of the creation routine in the original code:

procedure TMainForm.ProgramListBoxMouseUp(Sender: TObject;
  Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
var
  APoint: TPoint;
  Index: Integer;
begin
  if Button = mbRight then
    begin
      ShowMessage(TListBox(Sender).Name);  // This reports the correct name of all the Listboxes

      if FindComponent(TListBox(Sender).Name) <> NIL then // Returns NIL on all dynamic listboxes,
        ShowMessage('Found It!')                                         // even though sender name is correct...
      else
        ShowMessage('Couldn''t Find It ...');
    end;
end;

As the comments show, the correct ListBox names is returned if you right click on it.  However, if you call FindComponent using the correct name it returns NIL!  

Chris Bray.
ASKER CERTIFIED SOLUTION
Avatar of Member_2_248744
Member_2_248744
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
sorry. . . I should have said -
in the  
      procedure TMainForm.ProgramListBoxMouseUp  
 code above
Hi Slick812,

Thanks for that - said it was probably something stupid, didn't I?  Must be going daft in my old age :-)

Chris Bray.
procedure TMainForm.ProgramListBoxMouseUp(Sender: TObject;
                                          Button: TMouseButton;
                                          Shift: TShiftState;
                                          X, Y: Integer);
begin
  if Button = mbRight then
  begin
    ShowMessage(TListBox(Sender).Name);  // This reports the correct name of all the Listboxes

    if (Assigned(TListBox(Sender))) then
      ShowMessage('Found It!')
    else
      ShowMessage('Couldn''t Find It ...');
  end;
end;