This tutorial follows on from the Level Three tutorial about making arrays of controls. (Originally (and probably still!) called DT3a).
There is a search button at the bottom of the page.
It will show you how you can customise a standard Delphi component to give it the features you wish Borland had incorporated in the first place.
This is an early draft... apologies if there are mistakes. Please send me an email if you encounter any... or to say that you worked through successfully?
As you work through it, you might feel that you could accomplish what is here by more direct means. There is a penalty to pay, too, in that the component we are going to develop cannot be placed on the design-time form that is a major aid to the 'visual' aspect of Delphi programming. (I suspect that there are ways you COULD add your component to the Components Palette... but they are not covered here.) If you find those thoughts a serious problem, consider this: How else would you produce AN ARRAY of edit boxes, even without customisations?
All the completed program will do is provide an inches to centimeters converter. It won't even work both ways! However, by keeping the program simple, the essentials of customising a component should be kept clear.
I am endebted to Mr. Alan Lloyd of comp.lang.pascal.delphi.misc newsgroup for showing me how to customising a component. There is also a welth of information in the Delphi help file (of course) if you can find it (not always easy)... look under components, overviewof component creation.
Start a new project. I called my Demo, with my usual suffixes to distinguish forms, units, etc. In particular, to make the following work, name the form DemoF1.
Add StdCtrls to the Uses section. The TEdit control is defined in StdCtrls, so the compiler needs StdCtrls to create our customised TEdit.
Put a label on the form. Autosize=false. Top=50,Left=50,height=50,width=50.
Select the label. Do ctrl-c. Do ctrl-v three times. You should now have 4 labels.
Leaving the first where it was, drag the others so that you have two rows of two, neatly spaced. Now delete the first... our customised edit box will go there.
Make the captions of the upper and lower right hand labels 'Inches' and 'Cms'.
Make the name of the lower left label lOutput.
Just to get everything else working, put an ordinary edit box where the first label was.
Save what you've got so far. Run it and debug if necessary.. it shouldn't do anything yet, but it should run!
Program the edit box's OnChange event as follows:
As a first step, make it just
With that, any change in the edit box should put 4.50 in lOutput.
Next make edit box's text 0 and make the OnChange event
procedure TDemoF1.Edit1Change(Sender: TObject); var rInches:real; begin try rInches:=StrToFloat(Edit1.text); except on EConvertError do rInches:=0 end; lOutput.caption:=FloatToStrF(rInches*100/39.37,ffFixed,4,2); end;
Delphi will report the EConvertError if you make the contents of the edit box invalid for conversion to a number, but just click OK and then Run again.
Also, the insertion point indicator in the edit box disappears... but you can edit the edit box contents normally. (If someone could tell me how to avoid losing the IPI, I'd be grateful.)
When you've got this working, save. Next we will replace the standard edit box control with one of our own devising.
In the unit's Type section, add:
TBoydEdit = class(TEdit) public constructor Create(AOwner:TComponent;iTop,iLeft,iSize:integer); destructor Destroy; end;(*Declare type TBoydEdit*)
As you can guess, the name TBoydEdit is up to you, though convention suggests starting it with a T. The names AOwner,iTop and iLeft are also up to you. (I would have used something like compOwner, but Borland used AOwner) The first parameter of the Create method will always (?... comment form any expert who knows otherwise will be welcomed!) be there, and be of type TComponent. The other parameters are up to you... include whatever is needed for your customisation requirements. In this example, we are going to be able to say where the edit box will be and how big. It will always be square.... but you should be able to re-define it for some other rule, once you've studied this tutorial.
(You can't run the program at this stage)
Add the following to the implementation section of the program:
constructor TBoydEdit.create(AOwner:TComponent;iTop,iLeft,iSize:integer); begin end; destructor TBoydEdit.destroy; begin end;
Your program should run again, though it won't yet do anything it didn't do before.
revise the constructor (in the implementation section) as follows:
constructor TBoydEdit.create(AOwner:TComponent;iTop,iLeft,iSize:integer); begin inherited create(AOwner); parent:=TWinControl(AOwner); with Self do begin top:=iTop; left:=iLeft; width:=iSize; height:=iSize; visible:=true; enabled:=true; color:=clGreen; end;(*...with self*) end;
Again, your program should run, though it still won't yet do anything it didn't do before.
What properties can you set? What names do you use? Just look in the Delphi help file. If you are making a customised TEdit control, then the TEdit properties are available to you... and you must use the names defined by the TEdit. E.g., in the example above, top, left, width, height, visible, enabled, color.
Drag the edit box you gave your form to some out of the way place.
In the Var section, add
Add a OnCreate event to your form, and program it as follows:
If you run the program now, you should see a green edit box where the old one used to be. Entering data won't do anything yet. (Why green? Just to show it's not an ordinary edit box!)
Now we come to a further problem connected with the fact that the TBoydEdit version of the edit box is not registered and so it cannot be 'seen' by the object inspector. How do we get the program to process events arising from BoydEdit1? In particular, we need to write an event handler to react to changes in BoydEdit1.text. With the standard edit box, we just turned to the object inspector and clicked the OnChange event, and a skelton for a handler appeared.
First: What events can you attach code to? The answer is similar to the answer to the question above about what properties are available. If you are customising TEdit, then use the object inspector to look at TEdit's events. You'll see OnChange, OnClick, OnDblClick, etc.
The first step is to choose a name for the procedure that will handle the event from your customised control. For this example, I'm using the name BoydOnChange.
Now, in the With Self block, add a line to the control's create constructor saying
It will look as if you are merely declaring another property default. In a loose sense you are... you are declaring what procedure to execute when OnChange events arise from the control. Note that you have no choice over the name 'OnChange', though of course you could specify handlers for other events.
The next thing you must do is put
private procedure BoydOnChange(Sender:TObject);
in the declaration of the TBoydEdit type near the top of the program. It can go just before the word 'public'. (Sorry... at this point my understanding of public/private/published and implementation is too hazy to explain or defend details... but what I've aasid to do does work!)
And lastly, copy the old TDemoF1.Edit1Change, and make changes in the (**)'d lines to make it
procedure TBoydEdit.BoydOnChange(Sender: TObject); (**) var rInches:real; begin try rInches:=StrToFloat(BoydEdit1.text); (**) except on EConvertError do rInches:=0 end; DemoF1.lOutput.caption:=FloatToStrF(rInches*100/39.37,ffFixed,4,2); (**) end;
That should do it! Of course, the ordinary edit box put on the form early in the tutorial could now be deleted. If you decide to do this, you'll want to turn things like
procedure TDemof1.Edit1Change(Sender: TObject);...
will have to be taken out as well.
Notes to self...
>>> Write up as lower level tutorial Try..except..end
Click here to visit editor's freeware, shareware page.
Page WILL BE tested for compliance with INDUSTRY (not MS-only) standards, using the free, publicly accessible validator at validator.w3.org
....... P a g e . . . E n d s .....