For forums, blogs and more please visit our
Developer Tools Community.
By: Marco Canty
Abstract: The name of a component plays a fundamental role in Delphi (and C++Builder), but some of the features behind this property are far from well-known. By Marco Canty.
The name of a component plays a fundamental role in Delphi and C++Builder, but some of the features behind this property
are far from well-known.
Name and Tag are published properties defined in the TComponent class. They
are both available for each and every VCL component. Tag is there for your own personal use
-- the VCL never refers to it -- but the Name property plays a very special role. As I hope to show you in this article,
the Name property has a variety of subtle, largely unexplored aspects.
Delphi assigns names to components based on a simple convention: the class
name minus the first letter plus a sequencer number that distinguishes components of the same type within the same form
(or other component container, such as a frame or data module).
The first rule for the Name property is to give readable names to the components as soon as possible. Techniques range from adapted Hungarian notation, with the type prefacing the component role
(btnAdd) to minor changes to the generated names (ButtonAdd), to names indicating only the role and not the
type (Add). I don't like this last notation, though many of the demos
that ship with Delphi use it. I prefer the first sort of name. Your mileage
will almost certainly vary; there are as many variations on naming conventions as there are Delphi programmers.
It would be nice if Delphi generated names in a user-configurable way, so we
could ask the IDE to use btn as initial portion of the name generated automatically for any new TButton
Whatever you choose, give your components a name before writing code the code
that refers to them, as Delphi doesn't fix component references retroactively. Delphi fixes references from one component to another and updates the names of event handlers
(a Button1Click will become
btnAddClick). When assigning a name, remember that it must be a valid Pascal
identifier; no spaces or special characters are allowed. Every name must start with a letter or underscore followed by other letters, numbers or underscore characters.
Two components on the same form cannot have the same name. If you rename Button2
as Button1 and a component with this name already exists, the IDE will flag an error. Even when you create components at runtime, their names must be unique. This
rule is enforced by an ownership mechanism: All the components owned by a single
class must have unique names. By the way, this makes it possible to apply to an owner the FindComponent method, passing the name of a component as parameter.
There is an exception to this rule: You can have multiple components with the
same name as long as Name is set to an empty string. In this case there is no conflict, but also no way to find the components by
name. If you blank out the Name property of a component at design time, Delphi will remove the corresponding field from the form class declaration. The field can also be removed manually in the source code, in this case without affecting the component name.
At runtime, you might want to create unnamed components to avoid the minor hassle of generating unique
names. At design time, you might want to remove the names to save space in memory and reduce the size of the executable file for all the components you'll never refer to, from menu item separators to fixed labels. The only rule is to keep the name of at least one component of each
type. This will help you avoid problems with the Delphi linker and RTTI.
As the Delphi help files point out, the Name property "specifies the name of the control as referenced in code." This means that in the source code we can refer to a component by using its name.
But this is a simplistic view. The Name is a string, part of the component. When you type Button1 in the source code you are referring to a field of a form class. How do they relate? At design time, changing the name results in changing the field name as well. At runtime changing the name can result in disaster.
When Delphi creates a form it reads the corresponding DFM file embedded in the resources of the application,
creating the specified components and reassigning the streamed properties. While setting the component Name from the DFM file, the component looks into the published fields of its owner using TObject's FieldAddress method and assigns itself
to the corresponding field, if any. If you want to look up this code in the VCL source, the field connection takes place in the private SetReference method of
TComponent, called by SetName.
This code is not specifically related to streams, but is executed every time you call the SetName method by assigning a new value to the Name property at runtime. SetName calls SetReference twice, first to disconnect the current component from the
field and second to connect it to a new field corresponding to the new name. So by assigning a new name to a component at runtime the original form field (your usual reference to the component in the source code) will generally be set to nil. A simple
Button1.Name := 'new';
will cause any further reference to Button1 to produce an access violation!
The Delphi help file warns us to change control names only at design time but gives no clue why this is
sound advice. Although I don't recommend it as a common practice, the truth is
that the name can be changed at runtime. (Technically, the warning refers to the
Name property of the TControl class, not the TComponent class. But the only
difference between the two classes is that controls with a special style active
change their captions along with the names, assuming the two match.) This analysis
reveals why form fields referring to components must be published. Were the
fields corresponding to components private, the corresponding objects would not be able to find them and attach themselves to
The Name property performs a lot of magic behind the scenes, as it identifies a component within its owner and connects it to the owner field. The value of the name property and the form field generally match, but do not confuse
them -- they are separate. Strangely enough, the compiler name of a four-byte pointer and a string saved within an object look for each other and merge so well to become almost undistinguishable to
users...but not to an expert eye.
Could not retrieve comments. Please try again later.
Server Response from: ETNASC04