List of Delphi controls on a form – Tree hierarchy and flat list (FireMonkey) by Scott Hollows

emailx45

Местный
Регистрация
5 Май 2008
Сообщения
3,571
Реакции
2,438
Credits
573
List of Delphi controls on a form – Tree hierarchy and flat list (FireMonkey)
Scott Hollows - 12/Oct/2016
[SHOWTOGROUPS=4,20]
Get a list of all controls in your Delphi FireMonkey (FMX) form .

Examples included a flat list and a hierarchical “tree” list
Для просмотра ссылки Войди или Зарегистрируйся
This is the FireMonkey (FMX) version of this topic.
For the VCL version go here

controls_list_comparison_fmx


  • First Level
    A flat list showing all first level components on the form.
    “first level only” means buttons on panels are excluded
  • Full List
    A complete list showing all components on the form (all levels)
    Does not include components within frames
  • Hierarchical “Tree” list
    This includes components within frames
Filtering Out Junk
Doing this in FireMonkey is a bit more difficult than VCL due to the need to filter out lower level objects that you probably don’t care about. For example scroll bars on a memo.

To get the information that we need you need to work through two different lists

1) Children List
This is a list of direct (first level) children, so it excludes buttons on a panel

This also includes some junk that you will need to filter out (more on that later).
For example, in my first test an empty form contained a TRectangle with no name.
Код:
for i := 0 to self.ChildrenCount - 1 do
     memo1.Lines.Add (self.Children[i].name);

2) Components List
This is a list of all children, at all levels … flattened down into a single list

It will include lower level children such as a button on a panel
Код:
for i := 0 to self.ComponentCount- 1 do
     memo1.Lines.Add (self.Components[i].name);

First Level
To get a list of first level children, you need to get objects that appear in both lists. This will filter out the junk objects that you dont care about.
Код:
for i := 0 to self.ComponentCount - 1 do
    for j := 0 to self.ChildrenCount - 1 do
       if (self.Children[j]=self.components[i])  //same object
       then begin
            memo1.lines.Add  (self.components[i].Name);
            break; // we found a match. no need to continue
            end;

Hierarchy
This shows the key procedure to process all components recursively.

This works by getting objects that appears in both the Children list and the Components list. That logic filters out the junk objects mentioned above.
Код:
procedure TForm2.ProcessControlHierarchy (
                       aFMXObject : TFMXObject;
                       aLevel     : integer = 0
                       );
// process the control including its child objects
// example use
//   ProcessControlHierarchy (self); 
var
i : integer;
j : integer;
s : string;
vFMXObject : TFMXObject;
begin
inc (aLevel);

              // do something with the control here
              // example 1) display control info
  memo1.lines.Add (
         LeftPadString ('',(aLevel -1) * 6,' ') //indent based on level
      // + aLevel.ToString
         + ' '
         + aFMXObject.name
         + ' (' + aFMXObject.ClassName +')'
         );

for i := 0 to aFMXObject.ChildrenCount - 1 do // process children
     begin
            // special considerations for frames
     if  aFMXObject is TFrame then
         vFMXObject := aFMXObject
     else
         vFMXObject := self;   // the form

     for j := 0 to vFMXObject.ComponentCount - 1 do
         begin
         if (aFMXObject.Children[i] = vFMXObject.Components[j])
         then
             begin
             ProcessControlHierarchy (
                  aFMXObject.Children[i], aLevel
                  );
             break; // found match. no need to continue
             end;
         end;
    end;
end;

Test for your control types
I have mainly focused on visual objects in this post so the hierarchy code does not include non visual components.

If you want to include non visual component like TDataSource you will need to modify the hieararchy code. This is because TDataSources appears in the Components list, but does not appear in the Children list.


Disclaimers
I haven’t tested this for all types of controls, but it should be good enough for most situations.

[/SHOWTOGROUPS]