Delphi
Basics
The typical Delphi application:
- A typical Delphi application that creates a Windows-based
GUI exe file consists of:
- the project file (appname.dpr):
- this is created and maintained entirely
by Delphi when you select to create a new
project
- you can edit this file but avoid doing so
as much as possible (view via
Project:View Source)
- when compiled this will create the
appname.exe file
- at least one set of form files:
- formUnitName.pas:
- this is automatically created
when you add a form to your
project, Delphi actually creates
a new form automatically when you
create a new project
- when compiled this becomes a *.dcu
file
- this is an ascii text file
editable in notepad which
contains:
- keyword
"Unit"
then FormUnitName
- comments
as needed throughout the
unit which are indicated
by:
- // all characters to
right of this is comments
- {comment} allows
multi-line comments
- compiler
directives as
needed throughout unit:
- {$x} - the $
sign within brackets
indicates a compiler
directive not just a
comment!!
- you can enforce or
turn off various compiler
options (this can also be
done in Project options)
such as Range Checking,
Overflow Checking,
Resource files, etc.
- keyword
"interface"
which marks the beginning
of the interface section
which is public to other
units which has this unit
in their uses clause and
contains:
- a uses
clause:
- this contains all
other units that this
unit references
- Delphi automatically
adds and removes units
here as components are
dropped or deleted from
the form
- you can add other
units here or in a uses
clause in the
implementation section:
- eg. other forms you
may need to call
- type
declarations and
information relating to
them
- your custom
enumerated types
- the Form
declaration
- references to the
Form's fields (eg. list
of all components placed
on form)
- references to the
Form's routines that have
been used by any of the
components
- references to
additional routines and
variables that you have
created manually, these
can be placed in either a
"private" or
"public"
section which governs
whether or not other
units can access them
- var clause
which instantiates the
Form class as well as
allowing other variables
to be declared.
- keyword
"implementation"
which marks the beginning
of the implementation
clause which is private
to the unit and contains:
- a uses clause
(optional)
- routines
created by Delphi as
component
"events"
- routines
created manually:
- these are either
"procedures"
or "functions"
- whilst both can
change a variable's value
that has been sent to it
by reference (ie. when
the keyword var is used
in the routine's
declaration), only a
function can return a
"result" value
which may be of any type
as long as the type is
declared
- eg. procedure
TFrmMain.ChangeButtonColor(Sender:TObject);
- begin
- if (Sender is
TButton) then
//check to see that the
object which called this
routine - the
"Sender", is a
TButton)
- (Sender as
TButton).color := clRed;
//change its color to red
- end; //end
routine
- eg. function
TFrmMain.CalcSum(X,Y:Single):Single;
- begin
- result := X+Y;//instead
of this we could have
written CalcSum := X+Y;
- end;
- optionally:
- keyword
"initialization"
which marks beginning of
routines that must occur
initially
- keyword
"finalization"
which marks begiining of
routines that must occur
on termination of unit's
instance
- finally the keyword
"end."
marks the end of the
unit.
- formUnitName.dfm:
- this is automatically created and
maintained by Delphi and for most
purposes can be ignored
- it stores details about the form
and its components' properties
- it can be edited directly within
Delphi and this can be useful as
global search & replaces may
be time saving when significant
changes are made to the
components' properties.
Language
Basics:
- Classes vs Objects:
- class: define a type of object
by its properties, methods (eg. constructor,
destructor) and events
- object: physical representation
or instance of a class
- in Delphi, the components are derived from the
Visual Component Library (VCL) which unlike VB is
fully object oriented rather than using older
technology of object-based MS Foundation Classes
(MFC's)
- VCL heirarchy:
- TObject:
- all classes descend from the TObject
class which encapsulates all the
characteristics & behaviour common to
all classes in the VCL heirarchy and
provides run-time type identification
(RTTI) which allows one to query an
object at runtime and discover its class
name, whether a certain method is
available, etc.
- this means that you can write code that
assumes all objects have the ultimate
parent of TObject, hence the variable Sender
is of type TObject;
- TPersistent:
- adds 2 very important methods to
supply persistence (ability to
save properties & load them)
- SaveToStream;
LoadFromStream;
- TComponent:
- adds the following
behaviours and
properties:
- ability to be
installed on the
component palette
- ability to be dropped
onto the form at design
time
- ability to have its
properties set through
the Object Inspector
& Component editor
- name property
- TControl:
- defines behaviour for
visual controls such as:
- drawing routines
- standard windows
events
- containership
- TGraphicControl:
- components that must
draw themselves but can
never receive focus, thus
don't need a window
handle (eg. Image, Label,
Bevel)
- TWinControl:
- as for
TGraphicControl but can
receive focus thus need a
handle
- Component "helper" classes:
- TStringList - uses linked lists to create an
object that can hold as many strings as you wish
- TList - also uses linked lists but can hold any
type of object or pointer
- TCanvas - encapsulates a Windows device context
handling drawing of forms and the Printer object
- TPrinter - encapsulates details of Windows
printers
- TIniFile - allows easy access to read/write to
ini file format
- TRegistry - allows easy acces to read/write to
Windows Registry
- TRegIniFile - allows an ini-style method of
read/write to Windows registry
- Comments:
- comments are crucial for documentation of code to
help you and others at later dates understand the
code
- there are 3 types of comment markers in object
pascal:
- { comments } EXCEPT if {$....}
as this is a compiler directive
- (* comments *)
- // comments remainder of line
- Compiler directives:
- these are in a curly bracket followed by dollar
sign
- Routines:
- the general syntax for these is:
- routineType
routineOwner.routineName(params);
(:return value if function)
- optionally: var varName:VarType;
//declared variables
- begin
- <statement>;
- nb. x := 3; here := is used to
assign the value of 3 to the
variable x
- nb. x = 3; here = is used as a
boolean equal statement to test
if x = 3
- nb. reserved word exit
immediately exits the routine
without completing the remaining
statements
- end; //here the semi-colon
indicates the end of a compound statement
- routineType is either "procedure" or
"function".
- routineOwner is either the form in which it was
declared or if a unit then can be left blank.
- the declaration for the routine must be placed in
the interface part either "private" or
"public"
- Decision structures:
- if..then..else:
- if <logical expression> then
- begin <statement>;
<statement>; .... end
//note don't use semicolon before
an else!!
- //nb. if only one statement then
don't need the begin..end
- //nb. if a 2nd if statement
is used here, then the following else
belongs to the 2nd if NOT
the 1st!
- else begin....end;
- case statements:
- case <x> of // x must be
an ordinal (integer, char, boolean, or
enumerated type) NOT a string or float;
- value1: <statement>; //value
can be a single value or a range
such as 'A'..'Z'
- value2: <statement>;
- end;
- Looping structures:
- while..do:
- while <logical expression> do
- for..do:
- for <variable> := <initial
value> to (downto) <final value do
- repeat..until:
- repeat
- until <logical expression>;
- reserved words used in looping
structures:
- break: exits the loop
that contains it
- continue: skips the rest
of the loop statements and goes back to
the loop evaluation statement
- Testing class heritage and typecasting:
- Delphi allows a routine to be called from any
object and if the routine has a parameter that
can be used to notify the routine which object
called the routine as does all object events (eg.
Sender :TObject variable), then one can make use
of this to avoid duplicating code unneccesarily,
eg.
- if (Sender is TButton) then
//check that it really is a TButton else
the following may crash program
- (Sender as TButton).caption
:= 'New Caption';//typecast
Sender as a TButton so compiler
knows it has a caption property
- can also use C-style typecasting as follows:
- TButton(sender).caption := 'New
Caption';
- in general don't use this style as if the
typecast is invalid, the system may crash
whereas in the 'as' syntax, Delphi will
raise an exception
- however, may need to use it if:
- need to typecast in the
Evaluate/Modify dialog in the
debugger
- you want faster performance when
there are many iterations, but
make sure you check inheritance
to avoid invalid typecasts
- Exception handling:
- if you do not create an exception handling code
within a routine and an exception occurs then
Delphi will stop the routine and check each
calling routine in reverse order until it finds a
routine that can handle the exception, if none is
found, eventually the application object will
handle it with a generic dialog box but this may
crash your application and even your system.
- try..finally:
- try <statement>; finally
<statement> end;
- try..except:
- try <statement>; except on
E:exception do <statement> end;
- try <statement>; except
- on ExceptionType1 do
<statement>;
- on ExceptionType2 do
<statement>;
- end;
- try <statement>; except on
EType1 do
- begin
- ShowMessage('My error
message');
- raise; //this re-raises
exception to abort this routine
- end;
- end;
- creating your own exceptions:
- if <logical expression> then
raise Exception.create('My Error
Message');
- can also create your own type of
exception so that it can be checked when
it occurs to find out what type it is:
- type EInvalidBalance =
class(Exception); //place
this at top of type statement
above form
- raise
EInvalidBalance.create('Sorry,
Balance cannot be less than
zero');