Articles::Adding Additonal Functionality to TButton
At times the standard components provided with
Delphi do not give you all the functionality that you require, the
aim of this tutorial is to show you how to add and implement extra
properties to the TButton control. I did this in Delphi 3 so I will
also breifly go into how to create a new Package and add the New
component to it. The component is totally compatable with Delphi 2
but not Delph 1 as it uses some Windows 95 specific
messages.
Getting Started with
the new component
As we wish to keep all the
existing functionality of TButton and do not wish to rewrite it
ourselves, we will make our component a descendant of the TButton
Class hence keeping all of its functionality but still enabling us
to add the additional functionality that we need.
New Properties to be
Added
The properties that we are going to add are
:
MultiLine |
This is a Boolean - By setting this to true the caption on
the button will be displayed on more than one line (with word
wrap) if the button is not wide enough to hold it. |
HorizAlignment |
This property can be set to one of three values (which we
will define as a new type) its purpose will be to allow the
caption to be aligned on the horizontal axis (left, centre or
right) |
VerticalAlignment |
This property is very similar to HorizAlignment but its
used with regards to the vertical axis (top, centre or
bottom) |
We will now have to define 2 new types to be used whith setting
the different alignment properties, we could of done this by having
just an integer value so that different values would mean a
different alignment, but by defineing a new type it makes your code
a lot easier to read and maintain. The 2 new types are defined as
follows:
type THorizAlign =
(halLeft,halRight,halCentre); TVerticalAlign =
(valTop,valBottom,valCentre);
The Definition of the New
Class
TMultiLineBtn =
class(TButton) private
fMultiLine: Boolean; fHorizAlign :
THorizAlign; fVerticalAlign
:TVerticalAlign; procedure SetMultiLine(Value:
Boolean); procedure SetHorizAlign(Value:
THorizAlign); procedure
SetVerticalAlign(Value: TVerticalAlign);
protected procedure
CreateParams(var Params: TCreateParams);
override; public
constructor Create(AOwner: TComponent);
override; published
property HorizAlign: THorizAlign read fHorizAlign
write setHorizAlign default
halCentre; property VerticalAlign
:TVerticalAlign read fVerticalAlign write
setVerticalAlign default valCentre;
property MultiLine: Boolean read fMultiLine
write SetMultiLine default True;
end;
To summarize what we are doing
here:
The private section contains the new
properties and procedures needed for implementing the new component.
The protected section overrides the createParams procedure which is
used to actually implement the additional functionality, this will
be explained later. The create procedure is overriden in the public
section, this allows us to set our new properties to their Default
values when an instance of our component is created. The properties
in the published section will actually appear in the Object
Inspector and as we have defined a new type for the alignment
properties they will appear as combo boxes allowing easy changing of
their value. The way our alignment properties work is, if they are
read the value of its equivilent in the private section is returned
whilst if the use wishes to change a value the set procedure is
called, passing the new value as a parameter, this allows us to
update the control visually whenever the value is changed.
The Procedures
The Construtor
constructor
TMultiLineBtn.Create(AOwner: TComponent); begin
inherited Create(AOwner);
fMultiLine :=True;
fHorizAlign := halCentre; fVerticalAlign
:= valCentre; end;
The constructor inherits the
create method for a normal TButton, and sets all the default
values.
The set
procedure
procedure
TMultiLineBtn.SetVerticalAlign(Value:
TVerticalAlign); begin if
fVerticalAlign<>Value then
begin
fVerticalAlign:=Value; RecreateWnd;
end; end;
This procedure is called whenever
the VerticalAlign property is changed (both at design and run time).
It only does anything if the new value is different to the old one.
If the value is different then it sets the Private VerticalAlign
(fVerticalAlign) property to the new value and recreates the control
with these new settings. (This is explained furthur in the
CreateParams procedure).
procedure
TMultiLineBtn.SetHorizAlign(Value:
THorizAlign); begin if
fHorizAlign<>Value then
begin
fHorizAlign:=Value; RecreateWnd;
end; end;
procedure
TMultiLineBtn.SetMultiLine(Value:
Boolean); begin if
fMultiLine<>Value then
begin
fMultiLine:=Value; RecreateWnd;
end; end;
These two procedures work in the
same way as the SetVerticalAlign but changing there respective
values.
The CreateParams
Procedure
procedure
TMultiLineBtn.CreateParams(var Params:
TCreateParams); begin inherited
CreateParams(Params); case VerticalAlign
of valTop :
Params.Style:=Params.Style or BS_TOP;
valBottom : Params.Style:=Params.Style or
BS_BOTTOM; valCentre :
Params.Style:=Params.Style or BS_VCENTER;
end;
case HorizAlign
of halLeft :
Params.Style:=Params.Style or BS_LEFT;
halRight : Params.Style:=Params.Style or
BS_RIGHT; halCentre :
Params.Style:=Params.Style or BS_CENTER;
end;
if MultiLine
then Params.Style:=Params.Style or
BS_MULTILINE else
Params.Style:=Params.Style and not
BS_MULTILINE; end;
This is the crunch procedure of
our new component. It gets called whenever a button is created and
also when one of our new properties is changed (by means of the
RecreateWnd call). By checking in the win32 help file I noticed that
windows button control had the required functionality which has not
been encapsulated in TButton, so all that is needed is to set these
values whenever the new button is created or recreated. To start
with we inherit CreateParams from TButton thus letting it do any
initialization that it needs to, next depending on what are values
for the alignments and multiline are, we OR them with Style property
of the Params. Note the BS_ constants are all defined in the
windows.pas file. They are ORed because they do not take up all the
bits of the style property so by using OR with the constants only
the relevant bits are changed. For furthur information regarding the
different Styles supported in the windows API have a look at the
Button Styles section of win32.hlp.
Installing The Component
Delphi 2
From the component menu
select Install, this brings up the Install Components Dialog Button
box, which shows you what is presently installed and allows you to
add new components or remove them. We want to add a new component so
click on Add. It now asks you for the module name, this is just the
pas file that we have just created, so browse to the correct file.
Click OK and you'll notice that the path to the new component has
been added to the search path and that its name is in the Installed
Units list box. Now click on OK to rebuild the library. You will now
have a new tab on the component palette called Tutorials, with your
newly created button control on it, which you can now use as you can
all the other components.
Delphi
3
As Delphi 3 now supports packages (a different
way of storing components which I will go into more detail on in a
later article) I thought it would be a good idea to create a new
package and add the new button control to it. One of the ways of
doing this is to create a new package by selecting New... off the
File menu, add from the dialog box select Package. After you enter a
name and description for the new package (use your imagination here)
it brings up the Package Editor, which shows you what the package
contains and allows you to Add and Remove Components, Compile the
Package and Install it. The first thing we need to do is Add our new
component, so click on Add and Browse to your newly created pas
file, click on OK and you will see your unit has been add in the
Contains tab, all you need to do now is Compile it, and then Install
it, by clicking the relevant buttons. You will find that you now
have a new tab on the component palette called Tutorials, with your
newly created button control on it, which you can now use as you can
all the other components. |