Recently, I found a blog post about how to list components that are part of a form. I am a big fan of “good old programming principles” and thus I will provide a solution that is based on recursion. As a proof of concept I will provide a component at a later time that will once again show the luxury we have as a Delphi developer to wrap things in a component.
In order to list all the components on the form, I also dropped a TMemo and an additional button to initate the “logging” process.
procedure TFrmMain.btLogStartClick(Sender: TObject); begin // start logging with form LogComponent( self, 0 ); end; procedure TFrmMain.LogComponent(Root: TComponent; Level: Integer); var lLogLevel : string; i: Integer; begin // add spaces to signify the level lLogLevel := ''; for i := 0 to Level do begin lLogLevel := ' ' + lLogLevel; end; // log the component Log.Lines.Add( lLogLevel + Root.ToString + ' (' + Root.Name + ')' ); // call LogComponent for owned components for i := 0 to Root.ComponentCount - 1 do begin LogComponent( Root.Components[i], Level + 1 ); end; end;
Here we see a typical recursion. The button click event starts the process by providing the form itself and a “level” of 0. Every increment in level causes 2 spaces to be inserted in front of the component type and its name. In order to iterate all the components you only need two properties:
- ComponentCount : returns the number of components that a component owns
- Components : an array that contains all the components that a component owns
So, that’s it. It is only one for-loop and due to the fact that all components are derived from TComponent this will work for any component that might be dropped (or “added”) to a TForm. LogComponent will be called for every component and using the list of the component it owns, these components will be logged as well. The termination criteria is that there are only a limited number of components on a form, the number is not infinite and thus we have a recursion that will terminate at some point.
Here’s the demo in action. I simply added the logging to the last demo I presented on this blog. Stay tuned for the component.