如何在设计时获取表单上所有组件的列表?

Dmi*_*ryB 3 ide delphi components design-time

我需要在设计时获取表单上的所有组件的列表(不是控件,只是组件).

组件也必须在表单上作为设计时的24x24图像可见.

我可以使用这样的代码

procedure TForm2.GetComponentList(Memo1: TMemo)
var
  i: Integer;
begin
 for i := 0 to ComponentCount-1 do
   if (Components[i] is TComponent) and not (Components[i] is TControl) then
    Memo1.Lines.Add(Components[i].Name);
end;
Run Code Online (Sandbox Code Playgroud)

但在这里我会得到像TField等隐形组件.

我只需要IDE在Form上显示的组件为24x24位图.

可能我可以使用Open Tools API吗?

Del*_*ics 5

为(a例如其它部件的一部分创建的非可视组件TField一个内TDataSet的等)是含有成分的儿童.这种关系在DFM中很明显 - 如果将其视为文本,您将看到字段组件是相应数据集对象的子组件.

直接放在表单上的非可视组件(例如TDataset本身)是表单对象的子代:

object frmMain: TfrmMain
  ...
  object MyClientDataSet: TClientDataSet
    ...
    object MyClientDataSetID: TIntegerField
      FieldName = 'id'
    end
    object MyClientDataSetTitle: TStringField
      FieldName = 'title'
      Size = 255
    end
  end
  object MyDataSource: TDataSource
    DataSet = MyClientDataSet
    Left = 488
    Top = 120
  end
end
Run Code Online (Sandbox Code Playgroud)

即使非可视组件之间没有可视的父/子关系,非可视组件也不会知道他们是否有父母.

这是通过访问HasParent一个财产TComponent.

关键然而,一个表格认为是母体直接放置非可视组件.

因此,如果表单上的非可视组件(Form.Components中的项)的HasParentFALSE,则它是直接放置的组件,而不是某个其他组件的子组件.

只需修改if条件,如下所示:

if (NOT (Components[i] is TControl)) and (NOT Components[i].HasParent) then
  Memo1.Lines.Add(Components[i].Name);
Run Code Online (Sandbox Code Playgroud)

请注意,我已经删除了TComponent的测试,因为对于表单的Components属性中的项,它总是TRUE.