Przecież TCheckBox
to TControl
więc nie wiem po co iterować po wszystkich komponentach jak można tylko po kontrolkach. Błędem w tym kodzie jest użycie ComponentCount
zamiast ControlCount
. Oczywiście trzeba też pobierać kontrolki a więc Controls[i]
a nie Components[i]
.
Nie do tego te dwie listy służą. Nie chodzi o to z której klasy dany komponent dziedziczy, a o to, gdzie znajduje się dany komponent (w czym jest osadzony) i kto odpowiada za jego automatyczne zwolnienie, a więc o Parent
i Owner
.
W dużym skrócie:
-
Foo.Controls
— zawiera listę komponentów, dla których Foo
jest parentem. Z listy tej korzystamy wtedy, gdy chcemy uzyskać referencje wszystkich komponentów, które są osadzone wewnątrz Foo
i jest to osadzenie pierwszego poziomu.
Jeśli np. formularz zawiera GroupBox
, a w nim znajduje się Button
, to lista Controls
formularza będzie zawierać GroupBox
(pierwszy poziom osadzenia), ale nie będzie zawierać Button
(drugi poziom osadzenia). Aby uzyskać dostęp do Button
, trzeba wejść w listę GroupBox.Controls
.
-
Foo.Components
— zawiera listę komponentów, dla których Foo
jest ownerem. Z tej listy korzystamy wtedy, gdy chcemy mieć dostęp do wszsytkich komponentów zwalnianych automatycznie przez Foo
. najczęściej używa się tej listy do iterowania po wszystkich komponentach formularza, bez względu na to czy i gdzie są osadzone.
Jeśli np. formularz zawiera GroupBox
, a w nim znajduje się Button
, to lista Components
formularza będzie zawierać referencje do GroupBox
i Button
(poziom osadzenia nie ma znaczenia). Natomiast lista GroupBox.Components
będzie pusta, nieważne ile komponentów jest w nim osadzonych. W przypadku tworzenia formularzy w designerze, obiekt formularza będzie wyłącznym ownerem wszystkich wyklikanych komponentów.
Przykładowy formularz:

Drzewo osadzenia komponentów formularza:
Kopiuj
Form1
GroupBox1
CheckBox1
CheckBox2
CheckBox3
GroupBox2
Button1
Button2
GroupBox3
Button3
Zawartość list Controls
i Components
formularza i komponentów okienkowych:
Kopiuj
Form1.Controls GroupBox1, GroupBox2
Form1.Components GroupBox1, CheckBox1, CheckBox2, CheckBox3, GroupBox2, Button1, Button2, GroupBox3, Button3
GroupBox1.Controls CheckBox1, CheckBox2, CheckBox3
GroupBox1.Components
GroupBox2.Controls Button1, Button2, GroupBox3
GroupBox2.Components
GroupBox3.Controls Button3
GroupBox3.Components
Dla checkboxów i przycisków, listy Controls
również są dostępne, jednak będą one puste, dlatego że nie obsługują osadzania w sobie subkomponentów. Aby osadzanie było możliwe, w do zbioru flag z pola TControl.FControlStyle
należy dodać flagę csAcceptsControls
, a ta jest usuwana ze zbioru w konstruktorach klas komponentów, które mają osadzania nie obsługiwać (czyli np. w TCheckBox
i TButton
).
Myślę, że teraz wszystko powinno być jasne. ;)