There are several questions that pop up over and over again on the Inprise newsgroups. One such question (in various incarnations) is "How do I clear the text of all edit controls on a form?" This type of question is a common query from Visual Basic programmers moving to C++Builder. Those programmers are accustomed to using VB component arrays and want to accomplish the same thing in C++Builder. This article will explain how to use the VCL's Components property to enumerate all components on a form. We'll also show you how to use the dynamic_cast operator to determine the type of each component on the form.
The Components array is used internally by the VCL. Among other things, the array is used by the VCL when it deletes all owned objects for a form, usually when the form itself is deleted.
Memo1->Lines->Clear();
for (int i=0;i<ComponentCount;i++) {
String S = Components[i]->Name;
Memo1->Lines->Add(S);
}
This code is mostly self-explanatory. The loop starts at 0 (the component array
is 0-based) and stops at ComponentCount minus 1. Each component's Name property
is read and is added to the memo. As is our practice, we've broken the code
down to make it easier to understand. Most of the time you would write the code
as follows:for (int i=0;i<ComponentCount;i++) Memo1->Lines->Add(Components[i]->Name);Keep in mind that dynamically created components will have a blank Name property, unless you've specifically provided a name when you created the component. For example:
TLabel* label = new TLabel(this); label->Top = 20; label->Left = 20; label->Parent = this; label->Caption = "Hello";In this case, the label's Name property isn't assigned a value and will contain an empty string. You can use the pointer returned from the Components array directly if you only need to access properties of the component that are found in the TComponent class. For example, let's say you want to enumerate just those components that have their Tag property set to 1. In that case, the code would look like this:
for (int i=0;i<ComponentCount;i++) if (Components[i]->Tag == 1) Memo1->Lines->Add(Components[i]->Name);Here, only those components with a Tag property equal to 1 are added to the memo. If you want to access the properties of a particular type of component (a TEdit, for example), then you'll need to cast the TComponent pointer. Let's look at that next.
for (int i=0;i<ComponentCount;i++) ((TEdit*)Components[i])->Text = "";This code will work if, and only if, all components on the form are TEdits. If a component other than a TEdit is encountered, an access violation will almost certainly occur when you attempt to access the Text property. Given that, you should never use a C-style cast in this case. (In fact, we would argue that you should never use C-style casts in a C++ program.)
for (int i=0;i<ComponentCount;i++) {
TEdit* edit;
edit = dynamic_cast<TEdit*>(Components[i]);
if (edit)
edit->Text = "";
}
Each component in the Components array is cast to a TEdit. If the cast fails,
then the loop continues without further processing. If the cast succeeds, then
we use the pointer returned from dynamic_cast to set the Text property to an
empty string.
Let's look at another example. This code changes the font of all labels on the
form to bold:
for (int i=0;i<ComponentCount;i++) {
TLabel* label = dynamic_cast
<TLabel*>(Components[i]);
if (label)
label->Font->Style =
TFontStyles() << fsBold;
}
This code also illustrates the proper way to set a font's style. See the
article, "Dealing with sets," for more information on the correct way of adding
values to a set.
You can put any number of dynamic_cast calls within your enumeration loop. This
code, for example, combines the two operations we've seen up to this point:
for (int i=0;i<ComponentCount;i++) {
TEdit* edit = dynamic_cast
<TEdit*>(Components[i]);
if (edit)
edit->Text = "";
TLabel* label = dynamic_cast
<TLabel*>(Components[i]);
if (label)
label->Font->Style =
TFontStyles() << fsBold;
}
If a TEdit is found, then its text is cleared. If a TLabel is found, its font
style is changed to bold. All other components on the form are ignored.