Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
Member Area
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Become a Member
-Why sign up!
-Chat Online!
-Indexes NEW!!
-Build your resume
-Find a job
-Post a job
-Resume Search
-Link to us
Visit Embarcadero
Embarcadero Community
Published Objects in Components Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
Delphi 2.x
User Rating
No Votes
# Votes
DSP, Administrator
Reference URL:
			Author: Duncan Parsons

Some properties of a component can 'drop-down' to reveal other properties (such as 
a Font property reveals various properties within itself). These are objects within 
the component, and a simple demonstration of how to add you own new 'drop-down' 
properties is given here. (You can also get a Static Analogue Clock Component 


Please Note: I will only include here pertinent aspects of what is being explained. 
I will not flesh out all the examples for the sake of clarity. 

To include an object within a component is a fairly simple matter, simply declare a 
field, and make a property public. 

1   interface
3   type
4     TMyComp = class(TComponent)
5     private
6       fFont: TFont;
7     public
8       property Font: TFont read fFont write fFont;
9       constructor create(AOwner: TComponent); override;
10      destructor destroy; override;
11    end;
13  implementation
15  constructor TMyComp.create(AOwner: TComponent);
16  begin
17    inherited create(AOwner);
18    fFont := TFont.Create; //create the Object into the field reference,
19    //  so it will not raise an exception
20  end;
22  destructor TMyComp.destroy;
23  begin
24; //free the field to avoid memory leaks, etc.
25    inherited;
26  end;

NB: When creating Objects, ALWAYS remember to free them, unless a help file tells 
you overwise (happens very rarely, eg exception handlers). Notice that what is 
created in the constructor is explicitly freed in the destructor. 

This creates a fairly useless component admittedly, but it is an example after all! 
When accessing the Font property, it can be referenced in code using: 

27  begin
28    with MyComp1.Font do
29    begin
30      Color := clBlue;
31      Size := 10;
32    end;
33  end;

This is all well and good, but what about the Object Inspector? 
If we move the property from public to published, the Font property is now 
available, with the plus sign to 'drop-down' as required. 

This is a step in the right direction. 

However, this is not the whole story. What if we were devising a component which 
could logically take completely new objects as properties. For instance an analogue 
clock face - three similar objects would be obvious.. the hour, minute and second 
hands! Each is the same, save for customisable features, such as colour, thickness, 

So - let us construst our AnalogueHand object: 

34  type
35    TAnalogueHand = class
36      Colour: TColor;
37      Thickness: integer;
38    end;

Here is an object, descended from TObject, which has the properties we require. 

Let us put it into a Clock face component: 

39  type
40    TAnalogueClock = class(TGraphicControl)
41    private
42      fHourHand, fMinuteHand, FSecHand: TAnalogueHand;
43    protected
44      procedure SetHand(index: integer; value: TAnalogueHand);
45    public
46      constructor create(AOwner: TComponent); override;
47      destructor destroy; override;
48    published
49      property HourHand: TAnalogueHand index 0 read fHourHand write SetHand;
50      property MinuteHand: TAnalogueHand index 1 read fMinuteHand write SetHand;
51      property SecHand: TAnalogueHand index 2 read fSecHand write SetHand;
52    end;
54  //In the constructor, each field must be created separately, and freed on 
55  destruction: 
57  constructor TAnalogueClock.create(AOwner: TComponent);
58  begin
59    inherited create(AOwner);
60    //Set up the Hand Objects
61    fHourHand := TAnalogueHand.create;
62    with fHourHand do
63    begin
64      colour := clBlue;
65      Thickness := 2;
66    end;
67    fMinuteHand := TAnalogueHand.create;
68    with fMinuteHand do
69    begin
70      colour := clRed;
71      Thickness := 2;
72    end;
73    fSecHand := TAnalogueHand.create;
74    with fSecHand do
75    begin
76      colour := clRed;
77      Thickness := 1;
78    end;
79  end;
81  destructor TAnalogueClock.destroy;
82  begin
86    inherited;
87  end;
89  procedure TAnalogueClock.SetHand(index: integer; value: TAnalogueHand);
90  begin
91    case index of
92      0: fHourHand := Value;
93      1: fMinuteHand := Value;
94      2: fSecHand := Value;
95    end;
96    invalidate;
97  end;

Notice that the Hands are written to all using the same procedure, SetHand, each 
with a different index to refer to it. 

If we install this, we end up with our object, but the object inspector gives an 
Access Violation if we try to view the properties - not what we wanted! 

The reason being that to descend our Hand Object from TObject is the wrong 
ancestor.. For objects which are of a temporary nature, this is fine, but to allow 
properties to exist abit longer, to have their properties stored in a persistent 
fashion (put very simply!) - we must descend from TPersistent. 

So, our new hand declaration looks like: 

98  type
99    TAnalogueHand = class(TPersistent)
100     Colour: TColor;
101     Thickness: integer;
102   end;
104 //Rebuild, and the Access Violation has gone - hooray!! But, there are no 
105 subproperties!! An inspection of the Hand object could provide a clue.. with a 
106 standard component, for a property to appear in the object inspector, it must be 
107 published: 
109 type
110   TAnalogueHand = class(TPersistent)
111   private
112     fColour: TColor;
113     fThickness: integer;
114   published
115     property Colour: TColor read fColour write fColour;
116     property Thickness: integer read fThickness write fThickness;
117   end;

Rebuild again - and we have subproperties within properties, droppong down without 
Access Violations, etc. 

At runtime the new subproperties can be accessed by: 

118 with AnalagueClock1.HourHand do
119 begin
120   Colour := clOlive;
121   Thickness := 4;
122 end;
124 AnalagueClock1.SecHand.Colour := clFuchsia;

This has been a quick and simple overview to providing subproperties in a 
component. More complicated user defined objects can be created, which may have 
further subproperties (try publishing a TCanvas Object, and see how many layers you 

In summary: 

descend your new object from TPersistant (if it is COMPLETELY new - as in  the 
ensure that any methods declared in the object are written (such as constructors, 
setting procedures, functions, etc). - I've forgotten this a few times!! 
use the standard of fields and published properties (and any public as required). 
The published properties will appear as subproperties. 
ensure that when the new object is contained within a component that it is 
explicitly created and freed at the appropriate times. 

This worked example appears in an expanded form in the component attached to this 
article. I had a requirement for a Clock face, but I needed it to be static - for 
inputting. All the Clock faces I found were very nice, but the darn things moved!! 
So I created my own static analogue clock face. 

I make no apology for using British English within the component! Light 
diffractions have a 'U' (coloUr), and the free floating state contrary to digital 
has a 'UE' suffix (analogUE). If you don't like it - you have the source!!

Component Download: AnalogueClock.zip

Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10


Share this page
Download from Google

Copyright © Mendozi Enterprises LLC