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

How to get a list of all components on the Form at 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;

但在这里我会得到不可见的组件,如 TField 等

我只需要 IDE 在表单上显示为 24x24 位图的组件。

也许我可以使用 Open Tools API?

作为其他组件的一部分创建的非可视组件(例如 TDataSet 中的 TField 等)是包含组件的子组件.这种关系在 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

即使非视觉组件之间没有视觉 parent/child 关系,非视觉组件仍然知道它们是否有父级。

这可以通过 TComponent.

HasParent 属性 访问

然而,至关重要的是,Form 被认为是 directly 的父级非可视组件。

因此,如果 HasParent 对于表单上的非可视组件([ 中的项目)为 FALSE =59=]) 那么它是一个直接放置的组件,而不是其他组件的子组件。

只需修改你的if条件如下:

if (NOT (Components[i] is TControl)) and (NOT Components[i].HasParent) then
  Memo1.Lines.Add(Components[i].Name);

请注意,我已经删除了 is TComponent 的测试,因为这是 alwaysTRUE 对于表单的 组件 属性 中的项目。