Como ultima recomendacion, este tipo de problemas siempre suelo encapsularlos dentro de una clase; (un pequeño off-topic ) hace poco diseñe una clase similar para un programa que ya tenia que se encargaba de gestionar una lista de descendientes de una clase "Base", la cual era un descendiente de TFrame; la idea de estos frames es mostrar una pequeña ventanita con algun dibujo/pequeño listview/grafico de torta/etc con informacion estadistica, que venia de una DB
Entonces uno de los problemas era que tenia que existir una forma de "refrescar" cada x tiempo el contenido; por ello en la clase abstracta y padre se dispone del metodo RefreshData, entonces la solucion era, similar a la de este hilo, poner un timer y cuando se dispara el evento OnTimer, recorrer un contenedor de estos Frames e invocar al metodo RefreshData.
Es un monton de codigo que tiene que estar dentro del form Principal, que ya de por si tiene bastantes cosas, ahi ensuciando, hasta que decidi meterlo todo dentro de una clase. No solo que queda mas limpio, desacoplado, reusable y extensible, sino que tambien te permite tener mayor control. Por ejemplo se pueden crear eventos propios dentro de la clase, descartar un Refrescado (imaginen un evento OnBeforeRefresh)
Asi que cree una clase TWidgetManager, que es lo unico que paso a conocer mi Main form: toda la interaccion ahora ocurre entre propiedades, metodos y eventos. De hecho, esta clase es la que se hace cargo de controlar el Timer, y no el Form, puedo obtener una lista de todos los Widget, los Widgets "Visibles", los "Invisibles" (collapsed, que vendria a ser "contraido", y expanded); tengo un metodo Refresh publico, otro privado, puedo distinguir si es un Refresh "forzado", o uno privado (disparado por el timer), puedo invalidar un Refresh, y podria seguir agregando mas y mas funcionalidad
Dejo la parte interface de la clase para que se tenga un panorama mas completo..
type
TRefreshEvent = procedure(const IsUserRefresh: Boolean; var CanRefresh: Boolean) of object;
TWidgetManager = class
strict private
FWidgets: IList<TWidgetBase>;
FOwnsWidgets: Boolean;
FTimer: TTimer;
FBeforeRefresh: TRefreshEvent;
function GetWidgets: IEnumerable<TWidgetBase>;
function GetExpandedWidgets: IEnumerable<TWidgetBase>;
function GetCollapsedWidgets: IEnumerable<TWidgetBase>;
function GetCount: Integer;
function GetRefreshInterval: Cardinal;
function GetRefreshEnabled: Boolean;
procedure SetRefreshInterval(const Value: Cardinal);
procedure SetRefreshEnabled(const Value: Boolean);
procedure SetBeforeRefresh(const Value: TRefreshEvent);
procedure Refresh(const IsUserRefresh: Boolean); overload;
procedure AutoRefresh;
procedure OnTimerNotify(Sender: TObject);
public
constructor Create(const AOwnsWidgets: Boolean; const ARefreshInterval: Cardinal = 5000);
destructor Destroy; override;
function Add(AWidget: TWidgetBase): Integer;
procedure Delete(const AIndex: Integer); overload;
procedure Delete(AWidget: TWidgetBase); overload;
procedure Refresh; overload;
property Widgets: IEnumerable<TWidgetBase> read GetWidgets;
property ExpandedWidgets: IEnumerable<TWidgetBase> read GetExpandedWidgets;
property CollapsedWidgets: IEnumerable<TWidgetBase> read GetCollapsedWidgets;
property Count: Integer read GetCount;
property RefreshInterval: Cardinal read GetRefreshInterval write SetRefreshInterval;
property RefreshEnabled: Boolean read GetRefreshEnabled write SetRefreshEnabled;
property BeforeRefresh: TRefreshEvent read FBeforeRefresh write SetBeforeRefresh;
end;
Fin off-topic
Saludos