Delphi Study Notes

36
Introduction to visual programming RAD – Rapid Application Development IDE – Integrated Development Environment GUI – Graphical User Interface Form Designer: Design user interface for program (‘design mode’, execute program ‘run mode’) Object Inspector: set initial properties of all components in user interface Two tabs – Properties and Events ObjectName.PropertyName := value; Object Properties: Caption – caption on top of component (button, label, form, radio button) text string to identify object to user Name – Program code refer to component name. Change during design time only. TabOrder – Order which component receive focus when user press <Tab> or during runtime set component focus reday for input from user: edtText.SetFocus; Enabled – component is active or not (True or False) Color – colour of object (clPurple, clYellow,clBlue) Height – Vertical size of component (pixels) Width – Horizontal size of component (pixels) Top – Vertical position of top-left corner relevant to form (pixels) Left – Left side of component on form (pixels) Kind – Bitmap Button type (bkClose, bkOk, bkYes, bkNo, bkRetry) Text – Text for entering text during design or run time. Valid for Edit Components Clear – to clear component property during runtime: edtText.Clear; Readonly – able to enter text (True or False) Hint – Text to hint when cursor over item Showhint – Show or hide hint (True or False) Naming conventions: TButton: btnName Bitmap Button: bmbName TLabel: lblText TEdit: edtText TForm: frmName TRadioButton: radName TSpindEdit: sedName

description

Study Notes

Transcript of Delphi Study Notes

Introduction to visual programming

RAD – Rapid Application Development IDE – Integrated Development Environment GUI – Graphical User Interface

Form Designer: Design user interface for program (‘design mode’, execute program ‘run mode’) Object Inspector: set initial properties of all components in user interface Two tabs – Properties and Events ObjectName.PropertyName := value; Object Properties:

Caption – caption on top of component (button, label, form, radio button) text string to identify object to user Name – Program code refer to component name. Change during design time only. TabOrder – Order which component receive focus when user press <Tab> or during runtime set component focus reday for input from user: edtText.SetFocus;

Enabled – component is active or not (True or False) Color – colour of object (clPurple, clYellow,clBlue)

Height – Vertical size of component (pixels) Width – Horizontal size of component (pixels) Top – Vertical position of top-left corner relevant to form (pixels) Left – Left side of component on form (pixels)

Kind – Bitmap Button type (bkClose, bkOk, bkYes, bkNo, bkRetry) Text – Text for entering text during design or run time. Valid for Edit Components Clear – to clear component property during runtime: edtText.Clear; Readonly – able to enter text (True or False)

Hint – Text to hint when cursor over item Showhint – Show or hide hint (True or False)

Naming conventions: TButton: btnName Bitmap Button: bmbName TLabel: lblText TEdit: edtText

TForm: frmName TRadioButton: radName TSpindEdit: sedName

Event Handler: procedure TForm1.button1Click(Sender: TObject); begin //marks beginning of program statements make up event handler Form1.Color := clYellow; Form1.Caption := ‘Yellow’; Form1.Enabled := True; end; // end of procedure

end. // end of program, using full stop Events: OnClick – user click component Accelerator (hot) keys: Allow user operate program buttons from keyboard. Insert ampersand (&) in front of appropriate letter in Caption property. Assignment statement: Assign values to component properties (text, caption, color, ...) lblText.Caption := ‘New Text’; frmForm1.Color := clPurple; btnButton.Enaled := True; Transfer value of one object property to another: bntCalc.Caption := edtEdit.Text; Assignment Operator ‘:=’ Components from Standard Menu: Button // Press button on form to do action Edit //input text Label // display an output string value Frame // CheckBox RadioButton Components from Additional Menu: BitBtn Popup Menu during design time: press <Ctrl-Space> Constructing Comments:

//Text entered after double-slash { Text between left and right brace} (* Tesxt between left-parenthesis-plus-asterisk and asterisk-plus-right-parenthesis *)

Delphi distinguishes between simple statement and compound statements. A simple statement is one executable line of code (not one line of code in Code Editor). A compound statement is a block of simple statements surrounded by begin/end keywords.

//simple statement

Form1.Caption := 'Ha! New caption ';

//compound statement

begin

Top := Top - 10;

Width := Width + 5;

end

a semicolon (;) is always required to separate two simple statement.

Associating Variables with variable names: var NewText: string;

Variables in Pascal hold informations (values). Variables have to be declared before they can be used. We do this after the var keyword. The var keyword can be used in several places in the code, such as at the beginning of the code of a function or procedure, to declare variables local to the routine, or inside a unit to declare global variables.

When declaring a variable, we must state its type. The type of a variable defines the set of values the variable can have.

var

SomeValue : Integer;

NewAdress : string;

IsThisWorthy : boolean;

GimmeMoney : Currency;

Something : variant;

A, B, C : char;

Lookout : Pointer;

can declare more than one variable of the same type by placing a comma between them. (SomeValue is variable of Integer type.)

Assigning values to variables After declare variable, use to manipulate data in memory. Uses the := sign for assigning values to variables.

GimmeMoney := 323,23; //Curreny type variable

IsThisWorthy := True; //boolean type

NewAdress := 'My new home adress'; //string type

Delphi enforces strict rules on kind assignments make between variable types. Can't assign string value to currency type variable.

Constants (values that do not change during program execution) are declared using the const keyword. To declare a constant you don't need to specify a data type, but only assign an initial value.

const

Min = 30;

Max = 500;

Middle = (Max + Min) div 2;

ErrStr = 'Some errors occured';

MaxAmount = 123.45;

SomeValue := Middle + 200;

Variable Types: String // Series of characters String[15] // Specify maximum length for string Integer // Numbers Boolean // True or False Char // Sing Character Rules for variable names:

1) Name any length, but Delphi only use first 255 characters 2) First character must be letter or an underscore 3) Characters following first can be letters, numbers or underscores 4) No spaces allowed, and is case insensitive

ListBox components Add components to list box: Var Boy: string; Boy := edtName.Text;

lstBoys.Items.Add(Boy); // Add input from text box to list editName.clear; editName.SetFocus;

String Concatenation Concatenate one string onto end of another string using + sign TheOtherString := SthisString + ThatString; SpinEdit component: Found component Samples tab under tool pallet Value from SpinEdit component: Answer := SedName.Value; What is a Delphi unit? A Delphi unit is a separate file used to store procedures and functions. If you know what a form is, a unit is exactly the same, except it has no visual interface. So you can't put windows controls on it like buttons and edit boxes. A form has windows controls and their associated code behind them, a unit only has the code. Converting Integer to String: edtAnswer.Text := IntToStr(Answer); Numbers in strings: var Ninety: string; Ninety := ‘90’; Cannot do any arithmetic calculations Integer Arithmetric: + Addition

- Substraction * Multiplication DIV Division producing integer component (no remainder) MOD Integer remainder after division of integers

Sum := 10 + 3; Difference := 10 – 3; Product := 10 * 3; IntDivide := 19 DIV 5; // result is 3, discarding remainder Remainder := 19 MOD 5; // result is remainder 4 Floating point (real) numbers: Fractional parts, floating point or real data types Single 2.5 X 10E-45 ... 3.4 X 10E38 Double 5.0 X 10E-324 ... 1.7 X 10E308 Extended 3.6 X 10E-4951 ... 1.1 X 10E4932 Currency -922337203685477.5808 ... 922337203685477.5807 Convert Real number to string: edtEuro.text := FloatToStrF(Euro, ffFixed, 15,2); FloatToStrF(Value, Format, Precision, Digits); Also use FloatToStr(FloatValue);

Constants: Declaration of reserved word const followed by identifier, followed by equal sign and constant value

const ExchangeRate = 0.1236; Declare more than one const: const Greeting = ‘Hello’; //string DaysInWeek = 7; // integer InchToCm = 2.54; //real

Conversion Functions: IntToStr Convert integer to string StrToInt Convert string to Integer StrToFloat Convert string to floating-point number FloatToStrF Convert floating-point to string and format the string (digits after decimal) FloatToStr Convert floating-point to string (without formatting)

Boolean Expressions: Mathematical Notation Delphi Notation Meaning = = equal to ≠ <> not equal to < < less than > > greater than

<= less than or equal to

>= greater than or equal to

Price > 20.00 {True if Price greater than 20.00, otherwise false} Value <> 0 {True if value not equal to 0, otherwise false} X >= y {True if x greater than or equal to y, otherwise false}

The if ... then ... else statements If value1 = value2 then

lblEqual.caption := ‘TRUE’

else

lblEquation.Caption := ‘FALSE’;

!note no semi-column after if statements before else to continue Difference between = and := llblEquation.Caption = ‘FALSE’

and

lblEqual.Captioni := ‘FALSE’

First is Boolean expression comparing values of left side of ‘=’ with value of right. Values to either True or False. Second is assignment statement assign value on right of ‘:=’ to property (or variable) on left. Comparing Strings

Same way as comparing numbers with relation operators (< and >). String ‘A’ is less than ‘B’, ‘x’ is greater than ‘a’. One first in alphabet is smaller. With long strings, individual letters are compared one-by-one from left to right. ‘adam’ is less than ‘eve’, the ‘a’ comes before ‘e’, and ‘apple’ is greater than ‘adam’, because ‘p’ comes after ‘d’. Uppercase letters come before lowercase. ‘Z’ smaller than ‘a’, ‘A’ smaller than ‘a’. ‘Eve’ less than ‘adam’.

Ignoring CASE when comparing strings Use UpperCase or LoweCase functions if UpperCase(value1) = UpperCase(value2) then

lblEqual.caption := ‘TRUE’

else

lblEqual.caption := ‘FALSE’;

Alternative CASE conversion Edit component has CharCase property which can be set to ecUpperCase, ecLowerCase or ecNormal. If CharCase for edtValue1 to ecUpperCase in Object Inspector, the user’s input will be converted to upper case as he type.

The if ... then ... else statement General Format: If Condition then

Statement1

else

statement2;

Condition is Boolean expression. If True, then Statement1 execute. If False statement2 execute. Can leave out Else part if nothing should happen if statement is False. Statements can be single program, or compound statement group placed between Begin and End. Never use Semicolon after word Then or after word Else. No semicolon between statement1 and Else. Logical operators in Boolean expressions Addition to operators (<,>,=), Boolean can include logical operators and, or and not. Combine conditions with and and or operands to form compound Boolean expression. (value1 > 10) and (value1 < 20)

(value1 = 10) or (value1 = 20)

If apply not operator to condition, it returns negation of condition’s value. Change value from True to False not(value1 > 10)

return False if value1 is greater than 10 and True if less than or equal to 10. Value1 Value2 (Value1 and Value2) (Value1 or Value) Not(Value1) True True True True False True False False True False False True False True True False False False False True Order of precedence (operators in expression have same precedence and evaluated left to right)

1 Bracketed Expressions 2 The NOT operator 3 And 4 Or 5 Relational operators(>,<,=, etc). A and B or C

= FALSE and FALSE or TRUE //and has precedence over or

= FALSE or TRUE //evaluate 1st part (give FALSE)

= TRUE //FALSE or TRUE give result TRUE

A and (B or C)

= FALSE and (FALSE or TRUE) //brackets have precedence

= FALSE and TRUE // evaluate 2nd part (give TRUE)

= FALSE // FALSE and TRUE give FALSE

Min <= x and x <= Max, Delphi evaluate x and x, result compile error (Min <= x) and (x <= Max), Boolean expressions both sides of and evaluated and then and is applied to resulting Boolean values.

Compound statements If frmColour.color = clYellow then

begin

frmcolour.color := clPurple;

frmcolour.caption := ‘Purple’;

end

else

begin

frmColour.color := clYellow;

frmColour.Caption := ‘Yellow’;

end;

When more than one statement appear in Then or Else part, statements must be enclosed by Begin and End. Note no semicolon before else statement. Structuring if...then...else If Salary > 7000.00 then tax := salary * highTax else

Tax := salary * lowTax;

If slalary > 7000 then

Tax := salary * highTax else

Tax := Salary * lowTax;

If salary > 7000 then

Tax := slalary * highTax

Else

Tax := salary * lowTax;

Semicolons in if...then...else statements Rule1: Semicolon is not used after the word Then Semicolon after Then interpreted as end of if...then...else If x >= 50 then; //wrong – semicolon after then

Result := ‘Pass’

Else //error occur since else not

//considered as part of statement

Result := ‘Fail;

If x >= 50 then; //if x >= 50 then do nothing

Result := ‘Pass’; //this will always be executed

Rule2: Semicolon not used directly after word else. Semicolon after else will not cause syntax error, cause program to give incorrect result. If x >= 50 then

Result := ‘Pass’

Else; //else do nothing

Result := ‘Fail’ // always execute

Rule3: Semicolon directly before else will always report syntax error

Common Windows dialogs in Delphi Dialog box is window (or form in Delphi) appears on top of existing windows to display information to user or to get information from user. Windows dialog boxes OpenDialog, SaveDialog and PrintDialog appear as components in Dialogs tab of Component/Tool pallet Visual versus non-visual components Components like OpenDialog, SaveDialog, FontDialog are never visible to user during runtime. Delphi use non-visual components for ‘behind the scenes’ operations. Program make Windows dialog ot represents visible when user action requires that dialog. Execute method First statement of btnLoadClick event handler If opdOpenDemo.Execute then

Common dialog box open when its Execute method is called. Inside the If statement, call opdOpenDemo’s Execute method. Execute returns True if user choose Open button on dialog, and False if user choose Cancel. Since chose Open, Execute returned True. Dialog’s FileName property gets value user typed into File name input box. Since Execute return True, the Then part of If statement execute memDemo.Lines.LoadFromFile(opdOpenDemo.FileName);

LoadFromFile method loads contents of file name in brackets into Lines property of memDemo. Required file name obtained from FileName property of opdOpenDemo.

If condition also function call, as long as function return Boolean value. Exception Handling Can overwrite default exception handling by wrapping statement in Try block so program handle exception. //Loading text from a file

procedure TfrmDialogDemo.btnLoadClick(Sender: TObject);

begin

if opdOpenDemo.Execute then

try

memDemo.Lines.LoadFromFile(opdOpenDemo.FileName);

except

ShowMessage('Error loading file ' +

opdOpenDemo.FileName);

end;

end;

The try...except statement Delphi executes statements that follow the Try keyword. If exception raised by one of these statements, Delphi jumps to the statement following the Except keyword. Statements can correspond appropriately to the exception occurred. If no exception raised by Try block, Delphi skip Except block and continues with statement after end. Saving text to file

procedure TfrmDialogDemo.btnSaveClick(Sender: TObject);

begin

if svdSaveDemo.Execute then

memDemo.Lines.SaveToFile(svdSaveDemo.FileName);

end;

Need to investigate how to check if file already exist when saving, informing user file will be overwritten. Changing Memo’s font Changing font in Memo component, use Set Font button to display Windows Font selection dialog

procedure TfrmDialogDemo.btnFontClick(Sender: TObject);

begin

if fodFontDemo.Execute then

memDemo.Font := fodFontDemo.Font;

end;

TMemo Properties: Lines – contain lines of text displayed in the Memo

ScrollBars – vertical/horizontal scrollbars (ssVertical, ssHorizontal, ssBoth and ssNone) WordWrap – If true word displayed on next line if not fit into a line

Methods: lines. LoadFromFile – loads lines of text from text file Lines.SaveToFile – Save to file Use: Give user space to type text of more than one line Nested IF statement if IsMammal then lblClass.Caption := ‘Mammal’;

if IsReptile then

lblClass.Caption := ‘Reptile’;

if not (IsMammal) and not(IsReptile) then

lblClass.Caption := ‘Unknown’;

If first if is true, the rest should not be executed. Replace IF structure with Nested IF statement if IsMammal then

lblClass.Caption := ‘Mammal’

else

if IsReptile then

lblClass.Caption := ‘Reptile’

else

if not (IsMammal) and not(IsReptile) then

lblClass.Caption := ‘Unknown’;

Layout of Nested IF Statements If Condition1 then If Condition2 then Statment1 else Statement2 else Statement3; Else belong to nearest IF preceding it which does not already have an Else part. Alternative: If Condition1 then if Condition2 then Statement1 else Statement2 else Statement3;

Consider: If Condition1 then

If Condition2 then

Statement1

else

Statement2;

One Else part. Apply rule first IF preceding Else, line 2. IF in line 1 has only Then part. If want Else part belong to outer If, must place nested if...then between begin and end: If Condition1 then

begin

if Condition2 then

Statement1;

end

else

Statement2;

Then part of first IF consist only of compound statement between begin and end. Could not put semicolon after Statement1 to indicate second IF. Delphi syntax rule state never use semicolon in front of Else since will cause compile error. Rule1: No semicolon after Then Rule2: No semicolon directly after Else Rule3: No semicolon after Else

Nested If structure with multiple If statements: Series of nested If statements where every Else part consist of neste if..,then...else statements. if Condition1 then

Statement1

else if Condition2 then

Statement2

else if Condition3 then

Statement3

else

Statement4;

TCheckBox: Properties: Checked If true a tick appears in box; if false box is empty Prefix: chk... Use: True/False (or Yes/No) choice

The CASE Statement: procedure TfrmBursary.btnEvaluateClick(Sender: TObject);

var

Amount: String;

begin

case sedAverage.Value of

90..100 : amount := 'R10 000.00';

75..89 : if chkAccounting.Checked or chkEconomics.checked then

amount := 'R8 000.00'

else

amount := 'R5 000.00';

60..74 : if chkAccounting.Checked then

amount := 'R3 000.00'

else

amount := 'R 0.00';

else

Amount := 'R 0.00';

end;

lblAmount.Caption := 'Bursary of ' + Amount + ' is awwarded.';

end;

Structure of CASE Statement: Case selector of

Option1 : statement1;

Option2 : statement2;

.

.

OptionN : statmentN;

Else

Statement;

end;

Else part is optional. SELECTOR is variable, expression or component property of Char, Boolean or Integer data type. SELECTOR may not be real or string. Option1, Option2, ... may be of form:

1) Constant of same type as Selector 2) List of values of same type as Selector. Values separated by commas (1, 2, 3) If value of

selector equal to any one of these, this alternative is chosen 3) Range of values of same type as Selector (1..10) If value of Selector within range, this

alternative is chosen 4) Combination of 1, 2 and 3 above

Const Myvalue = 100;

Var

SelectValue: integer;

Begin

SelectValue := seDemo.value;

Case SelectValue of

Myvalue : lblDemo.Caption := ‘Option type 1’;

40, 50, 60 : lblDemo.Caption := ‘Option type 2’;

70..99 : lblDemo.Caption := ‘Option type 3’;

1..39, 41..49, 51 : lblDemo.Caption := ‘Option type 4’;

Else

lblDemo.Caption := ‘Not in one of the options’;

end;

end;

For Char: ‘A’..’H’ : A to H

‘I”..’L’, ‘N’..’P’ : I to L, then N to P

‘M’ : Single character M only

Can also be compound statements enclosed within begin ... end. When is CASE statement preferable to IF statement:

CASE statement generally preferable to multiple alternative IF because easier to programmer to read and understand. CASE statement used only if all alternative options depend on value of same ordinal variable. If choice depends on different variables, real or string variable, nested IF statements must be used. CASE statement can be replaced with multiple IF structure, but not all multiple IF can be replaced with CASE

Generating words from characters Valid characters: ‘a’ ‘A’ ‘n’ ‘9’ ‘0’ ‘*’ ‘,’ ‘ ‘

Last character is single space. Invalid Characters: ‘ab’ //string contains two characters

‘b ‘ //string of 2 characters: ‘b’ and a space

‘’ //empty string contains no characters

Character can be treated as string, reversal not true. Var

Ch: char;

Str: string;

Begin

Ch := ‘a’;

Str := Ch; //character ‘a’ converted to string

Ch := Str; //error: incompatible types

To specify character inside string, need to specify index in square brackets Ch := Str[1]; //first character of the string converted to character Input Dialog boxes Input box is standard Delphi dialog box. Includes space for user to type input value in string format and always has OK and CANCEL button Surname := InputBox(‘User input’, ‘Enter a surname’, ‘’);

Will open dialog box with caption ‘User input’, the prompt ‘Enter a surname’ and the empty string as default input value. When click OK, InputBox statement return string to program where assigned to variable Surname. If click CANCEL, the default string is returned.

String Processing 1) Delete specific section in string 2) Insert substring into string at given location 3) Get length of string 4) Find position of substring in string 5) Extract part of string

Finding substring in a string: Position := Pos(StrToFind,TextToSearch);

Return position where located. Assign value to variable Position. Position := Pos(‘is’,’This is it!’);

Stores the integer value 3 in variable Position, because first occurrence of ‘is’ is in ‘This’.

function Pos(Str, Source : string): integer; Returns an integer specifying the position of the first occurrence of one string within another. Pos looks for the first complete occurence of Str in Source. If it finds one, it returns the character position in Source of the first character in Str as an integer value, otherwise it returns 0. Pos is case sensitive.

function PosEx(Str, Source : string, StartFrom : cardinal = 1): integer;

Returns an integer specifying the position of the first occurrence of one string within another, where the search starts at a specified position. PosEx looks for the first complete occurence of Str in Source, beginning the search at StartFrom. If it finds one, it returns the character position in Source of the first character in Str as an integer value, otherwise it returns 0. PosEx also returns 0 if StartFrom is greater then Length(Source) or if StartPos is < 0

Delete a substring from a string delete(TextToSearch,Position,length(StrToFind));

Start at position Position, it deletes the number of characters given by third value. Number of characters is length of StrToFind which get from Length(StrToFind) procedure Delete(var S: string; Index, Count : Integer)

Removes Count characters from a string S, starting at Index. Delphi leaves the string unchanged if Index is not positive or greater than the number of characters after the Index. If Count is greater than the rest of the characters after the Index, the rest of the string is deleted.

function Length(const S: string): integer

function Length(const S: array): integer

Returns an integer containing the number of characters in a string or the number of elements in an array. For an array, Length(S) always returns Ord(High(S))-Ord(Low(S))+1

Inserting a Substring into a string Insert(ReplaceStr,TextToSearch,Position);

Insert ReplaceStr into TextToSearch at position Position. Sentence := ‘what inserted?’; Insert(‘is ‘, Sentence, 6); procedure Insert(Source : string; var S : string; Index : Integer): string;

Inserts a substring Source into a string S at a given position Index. If Index is zero or negative Source is inserted at the beginning of S. If Index is greater than the Length of the string, Source is added to the end of S.

Copy part of a string Substr := Copy(TheString, BeginPosition, Len);

Copies substring in TheString from character in BeginPosition and containing Len characters to variable SubStr. TheString must be character string while BeginPosition and Len must be integers. If BeginPosition is greater than length of TheString, empty string is returned. If Len specifies more characters than remain from position BeginPosition, whatever is there is returned. Word := copy(‘This is copied’, 1, 4);

Assigns string ‘This’ to word.

function Copy(S; Index, Count: Integer): string; function Copy(S; Index, Count: Integer): array; Returns a substring of a string or a segment of a dynamic array. S is an expression of a string or dynamic-array type. Index and Count are integer-type expressions. Copy returns a string containing a specified number of characters from a string or sub array containing Count elements starting at S[Index].

If Index is greater than the length of S, Copy returns a zero-length string ("") or an empty array. If Count specifies more characters or array elements than are available, only the characters or elements from S[Index] to the end of S are returned.

To determine the number of characters in string, use the Length function. A convenient way to copy all the elements of S from the starting Index is to use MaxInt as Count.

Trim String

function Trim(const S: string): string;

Returns a string containing a copy of a specified string without both leading and trailing spaces and non-printing control characters.

Dialog box examples: // Simple ShowMessage dialog

ShowMessage(‘Simple show message example’);

// Input dialog

//Note: User Input is of type string

UserInput := InputBox(‘The Caption’ , ‘Please enter

something:’, ‘Something’);

// Warning dialog with OK button

MessageDlg(‘ This is a warning’, mtwarning,[mbOK],0);

//Information dialog with OK

MessageDlg(‘ This is some informationi’,

mtInformation,[mbOK],0);

// Error dialog with OK and Abort

If MessageDlg(‘This is an error’,mtError,[mbOK,mbAbort],0) =

mrOK then

// execute if user clicks OK

Else

//execute if user clicks Abort

// Confirmation dialog with Yes/No

If MessageDlg(‘Are you sure you want to exit?’,

mtConfirmation, [mbYes, mbNo], 0) = mrYes then

//execute if user clicks Yes

Else

// execute if user clicks No

General format of MessageDlg function: MessageDlg(StringToDisplay, TypeOfMessage, whichButtons, HelpTopic);

- StringToDisplay is message displayed inside dialog - TypeOfMessage is Delphi constant (mtWarning or mtError) determains icon and box

caption - whichButtons is Delphi constants represent selection of standard buttons. Exmaple OK

button ([mbOK]), OK and Abort ([mbOK, mbAbort]) and [mbYes, mbNo] - HelpTopic is integer value, normally 0

Handlin exceptions using message dialogs Procedure TfrmComission, btnCalculateClick(Sender: TObject);

Var

Sales, Comission: doubl;

Begin

Try

Sales := StrToFloat(edtSales.Text);

Except

If MessageDlg(‘unable to process sales value ‘ +

edtSales.Text, mtError, [mbOK, maAbort],0) = mrOK then

begin // user click OK

edtSales.SetFocus;

exit; //jump out of event handler

end

else // user click Abort

Close; //end the program

End; // end of try ... except

Description The MessageDlg function is used to display messages to the user. These

messages may be informational, or warnings or whatever. There is complete freedom over

the choice of buttons that the user may press to acknowledge the dialog.

For example, the user may be shown an error message, and be allowed to abort, retry or

cancel the erroneous process.

The DialogType may have one of the following enumerated values:

mtWarning Displays a exclamation symbol

mtError Displays a red 'X'

mtInformation Displays an 'i' in a bubble

mtConfirmation Displays an question mark

mtCustom Displays just the message

The Buttons value may be one or more of the following enumerated values :

mbYes Displays a 'Yes' button

mbNo Displays a 'No' button

mbOK Displays an 'OK' button

mbCancel Displays a 'Cancel' button

mbAbort Displays an 'Abort' button

mbRetry Displays a 'Retry' button

mbIgnore Displays an 'Ignore' button

mbAll Displays an 'All' button

mbNoToAll Displays a 'No to all' button

mbYesToAll Displys a 'Yes to all' button

mbHelp Displays a 'Help' button

You specify these values comma separated in square brackets, as in the second code example.

Delphi provides a number of predefined button combinations:

mbYesNoCancel = [mbYes,mbNO,mbCancel]

mbYesAllNoAllCancel =[mbYes,mbYesToAll, mbNo,mbNoToAll,mbCancel]

mbOKCancel =[mbOK,mbCancel]

mbAbortRetryCancel =[mbAbort,mbRetry,mbCancel]

mbAbortIgnore =[mbAbort,mbIgnore]

Now Delphi seem to have made a design error when setting the return value from the dialog

box. Instead of specifying the enumeration value of the button pressed, it uses a completely

different set of enumeration names:

mrYes = 6

mrNo = 7

mrOK = 1

mrCancel = 2

mrAbort = 3

mrRetry = 4

mrIgnore = 5

mrAll = 8

mrNoToAll = 9

mrYesToAll = 10

The values given are the numerical values of these enumerations, given in the numerical

order that the mb equivalents are defined. This is very odd.

Additionally, these values are defined in the Controls unit, not the Dialogs unit.

Note that the Help button has no equivalent return value. This is because it does not

terminate the dialog.

The HelpContext value is used in conjunction with the Help button. It's use is beyond the

scope of Delphi Basics.

Repetition

The For Loop for count := sedLower.Value to sedUpper.Value do

Starts a loop that executes a finite number of times Counter Driven Loop

1 for Variable := Integer Expression to|downto Integer Expression do

statement;

2 for Variable := Char Expression to|downto Char Expression do Statement;

3 for Variable := Enum Expression to|downto Enum Expression do Statement;

// Loop 5 times

For i := 1 to (10 div 2) do

ShowMessage('i = '+IntToStr(i));

For c := 'E' downto 'A' do

ShowMessage('c = '+c);

Structure: For CounterVariable := LowValue to HighValue do

Statement;

For x := 10 to (y*10-30) do ...

For x := 100 to 50 do ... //never executed since smaller

//bigger than upper value

For c := ‘a’ to ‘z’ do ... //execute 26 times

For c := ‘a’ to ‘a’ do ... //executed once

For z := HighValue downto LowValue do ... //count down

Can also be used with compound statements starting with BEGIN and ending with END;

The Random function Generating random number from 1 to 6: Throw := Random(6) + 1;

Random(6) generate numbers between 0 and 5. Generate a random floating point or integer number

1 function Random : Extended; 2 function Random ( LimitPlusOne : Integer ) : Integer;

The Random function generates random numbers. They can be floating point numbers in the range : 0 <= Number < 1.0 or integer numbers in the range : 0 <= Number < LimitPlusOne Delphi uses a pseudo random number generator that always returns the same sequence of values (232) each time the program runs. To avoid this predictability, use the Randomize procedure. It repositions into this random number sequence using the time of day as a pseudo random seed.

Randomize Reposition the Random number generator next value procedure Randomize ;

The Randomize procedure is used in conjunction with the Random function. It repositions the random number generator in its sequence of 232 pseudo random numbers. Randomize uses the time of day as the seed for this repositioning, so should provide a reliable method of creating an unpredictable sequence of numbers, even if they are a part of a predetermined sequence. // Get an integer random number in the range 1..100

ShowMessage('Fixed first 5 random numbers');

for i := 1 to 5 do

begin

int := 1 + Random(100); // The 100 value gives a range 0..99

ShowMessage('int = '+IntToStr(int));

end;

// Now randomize to reposition

Randomize;

ShowMessage('');

// Get an integer random number in the range 1..100

ShowMessage('Random next 5 numbers');

for i := 1 to 5 do

begin

int := 1 + Random(100); // The 100 value gives a range 0..99

ShowMessage('int = '+IntToStr(int));

end;

Fixed first 5 random numbers

int = 1

int = 4

int = 87

int = 21

int = 28

Random next 5 numbers

int = 35

int = 74

int = 45

int = 50

int = 31

Nested For Loops For OuterChar := ‘a’ to ‘e’ do

Begin

MyString := ‘’;

For InnerChar := ‘a’ to OuterChar do

MyString := MyString + InnerChar;

lstStrings.Items.add(MyString);

end; Result: ‘a’

‘ab’

‘abc’

‘abcd’

‘abcde’

The While ... do statement General purpose loop, can handle counter-controlled loops as well as ‘conditional’ loops. Conditional loop number repetitions determined by condition (ie Boolean expression). While loop, the loop body repeats as long as certain condition is True and end when that condition become False. Implements iteration structure that repeats statements while some condition is True While Condition do

Statement;

Repeat statements whilst a continuation condition is met While Expression do Statement;

The While keyword starts a control loop that is executed as long as the Expression is satisfied (returns True). The loop is not executed at all if the expression is false at the start. You need Begin or End markers if multiple statements are required in the loop. It is used when it is important that the statements are at only executed when necessary. // Display squares of integers until we reach 100 in value

While sqrNum <= 100 do

begin

// Show the square of num

ShowMessage(IntToStr(num)+' squared = '+IntToStr(sqrNum));

// Increment the number

Inc(num);

// Square the number

sqrNum := num * num;

end; Can replace any For Loop with While Loop. Sum := 0;

for count := sedLower.value to sedUpper.value do

sum := sum + count;

While loop:

Sum := 0;

Count := sedLower.value;

While count <= sedUpper.value do

begin

Sum := sum + count;

Count := count + 1;

End;

For loop automatically sets Count initially to the value in sedLower, While loop have to include assignment to do this. Rules for using While..do statements:

Rule1: Variable(s) appear in loop condition must be initialized before While Loop encountered. Called loop control variable(s).

Rule2: Inside loop body the value of loop control variable(s) must be modified to ensure loop condition become False at some stage, otherwise program will continue forever.

Repeat ... Until Implement iteration structure of which body always execute at least once Repeat

Statements sequence (loop body)

Until Condition;

Repeat statements until a termination condition is met Repeat

Statement1;

{Statement2;

...}

Until Expression

The Repeat keyword starts a control loop that is always executed at least once, and which terminates when the Expression is satisfied (returns True). There is no need for Begin or End markers - the Repeat and Until keywords serve that purpose. It is used when it is important that the statements are at least executed once.

Arrays and Indexes

Strings and indexes To get copy of first letter of string FirstLetter := Surname[1];

Index to first character of a string is 1. First element of other lists (items in ListBox) has index 0 Reversing string entered: Procedure TfrmReverseWord.btnReverseClick(Sender: TObject);

Var

Word, NewWord: String;

Index: Integer;

Begin

Word := edtWord.Text; // copy input string to variable

NewWord := ‘’; // Initialize NewWord to empty string

For Index := length(Word) down to 1 do // working from end

NewWord := NewWord + Word[Index]; // append char

ediWord.text := NewWord;

end;

Following will also solve problem correctly For index := 1 to length(Word) do

NewWord := Word[Index] + NewWord;

Arrays Is a data structure allows storing set of data items of same type under single name. Compare array with Items property of ListBox (or Memo), which also store list of data items in one structure. Difference is elements of array can be of any Delphi data type, not just strings as ListBox. Var NamesArray: array[1..20] of String;

Refer to individual elements with NameArray[1], ect, or with integer NamesArray[Index] 1 to 20. Lower bound of index range neet not be 1 Var TotalRainfall: array[1990..1999] of double;

Holds 10 rainfall figures relevant to year as index, more meaningful than using 1 to 10. Assignment statement TotalRainfall[1990] := StrToFloat(edtInput.Text);

Or

NamesArray[1] := ‘James’;

Looping through an array For Loops useful accessing and manipulating arrays.

Sum := 0;

For Counter := 1990 to 1999 do

Sum := Sum + TotalRainfall[Counter];

Dynamic Arrays Do not know how many elements there will be. When declare dynamic array, leave out the index range Var

ManyWord: array of string;

Number of elements is unknown. Before using array, size must be set by calling SetLength procedure SetLength(ManyWords, 10);

Dynamic array indexed from 0 to number of elements – 1. In example, ManyWords[0] is first element and ManyWords[9] is last element.

Initialising Arrays and Array Constants Initialising array and give its values when declared. Notation used for array constants. Array constants are arrays which do not change. Const

BoxinWeightLimits: array[1..10] of integer = (48, 51, 54, 57,

60, 64, 69, 75, 81, 91);

Two-dimensional Arrays Multi-dimensional arrays store tables with several rows and columns (like spreadsheet) Var Rainfall : array[1995..1999, 1..12] of double;

Declare two-dimensional array with 5 rows (indexed 1995 to 1999] and 12 columns (indexed 1 to 12). Each row store the 12 monthly rainfall figures for the relevan year.

The ComboBox component Looks like edit box with little down arrow to display list of options from which user can choose. TComboBox Properties Items Contains string that appear in drop-down list ItemIndex Index of currently selected item in list. Value -1 if no item selected Items.Count Number of items in the ComboBox Style Display style of ComboBox. Set property to csDropDownList result

user cannot enter text manually. Style csDropDown allow user to enter text.

Methods Item.Add Add string to end of list of items Prefix cbo...

Use Edit box with scrollable drop-down list attached. User can either select from list or type directly into edit box.

Const

Cities: array[1..3] of string = (‘Durban’, ‘Cape Town’,

‘Johannesburg’);

For I := 1 to 3 do

cboFromCity.Items.Add(Cities[I]); //Add cities to ComboBoxes

dboFromCity.ItemIndex := 0; // default index of ComboBox to 1st City

ListBoxes TListBox Properties ItemIndex Gives index of currently selected item in list. Value -1 no item

selected Item.Count Number of items listed in ListBox Prefix lst... Suppose have ListBox called lstName, then lstNames.Items[0] is first item and lstNames.Items[NoOfItems – 1] is the last item. NoOfItems is number of items in ListBox and given by property lstNames.Items.Count Load from file: lstNames.Items.LoadFromFile(dlgLoad.FileName);

To clear liest use: lstNames.Clear;

lstNames.SetFocus;

Deleting item from the list lstNames.Items.Delete(Index);

Index is the current item to be deleted. Index appear in round brackets. Delete method of Items property and Index is parameter (not an index) that is passed to that method. When value in square brackets follow reference list (eg lstNames.Items[Index], where lstNames.Items refer to list), value is an index to specific value in the list.

RadioGroups Special GroupBox that contains only RadioButtons. To add RadioButtons to RadioGroup edit Items property in Object Inspector. Each string in Items represent Caption of a RadioButton. Number of strings in Items property determines number of RadioButtons in the group. ItemIndex property (integer) indicates which RadioButton in group currently selected. If value 0, 1st button selected. If none, value is -1. TRadioGroup Properties Items Contains Captions of RadioButtons appear in group ItemIndex Index of currently RadioButton in RadioGroup. Value is -1 if none

Selected Items.Count Number of RadioButtons in RadioGroup Columns Integer value determine number of columns in which RadioButtons

Arranged inside RadioGroup. Default value 1 makes buttons appear in single column

Events OnClick Activated if user clicks any RadioButtons in RadioGroup Prefix rgp... Use GroupBox contains only RadioButtons. Number of RadioButtons and Captions

determined by strings caontained in Items propert. Using Case statements with Radio Group Case rgpAverage.ItemIndex of

-1 : MessageDlg(‘Indicate average score.’, mtWarninig,

[mbOK],0);

0 : Amount := ‘R10 000.00’;

1 : If chkAccounting.Checked or chkEconomics.Checked then

Amount := ‘R8 000.00’;

Else

Amount := ‘R5 000.00’;

2 : If chkAccounting.Checked then

Amount := ‘R3 000.00’;

End;

Events and Parameters

Event-driven Programming Stages to the event-processing sequence

1) Some action (’event’) occurs 2) Windows detects this event and sends event message to Delphi 3) IF programmer created event handler, Delphi initiates the event handler. If no linked event

handler, Delphi discard event message from Windows Because of GUI Delphi programs are event-driven. Event handler is group of program statements, (‘mini-programs’) attached to an event, runs whenever event occurs. OnMouseMove event handlers The mouse-click is common user event, alternative OnMouseMove

There are three fundamental mouse event handlers: OnMouseDown, OnMouseMove, and OnMouseUp. The MouseUp and MouseDown event handlers take the same five parameters as follows (the MouseMove lacks a Button parameter):

Sender - The object that detected the mouse action. Button - Indicates which mouse button was involved: mbLeft, mbMiddle, or mbRight. Shift - Indicates the state of the Alt, Ctrl, and Shift keys and the state of the mouse buttons

when the event occurred. X, Y - The pixel coordinates of the mouse pointer in the client area of the Sender.

OnMouseMove occurs when the user moves the mouse pointer while the mouse pointer is over a control. Since the OnMouseMove event handler will be called relatively frequently, any code inside this event handler will be executed often.

As we know, we can combine the keyboard with the mouse. For example, we can have the Shift-Move combination draw a circle. Let's see MouseMove in action (new project/new form):

procedure TForm1.FormMouseMove(Sender: TObject;

Shift: TShiftState; X,Y: Integer) ;

begin

if ssShift in Shift then

Canvas.Ellipse(x-20,y-20,x+20,y+20)

else if ssCtrl in Shift then

Canvas.Rectangle(x-20,y-20,x+20,y+20) ;

end;

With this code, moving the mouse over the form causes circles to follow the mouse if Shift key was pressed during move, and rectangles if Ctrl key was pressed

procedure TfrmShow.bmbCloseMouseMove(Sender: TObject; Shift:

TShiftState; X, Y: Integer);

begin

bmbClose.Font.style := [fsBold,fsunderline];

end; //Change font when mouse move over botton

procedure TfrmShow.FormMouseMove(Sender: TObject; Shift:

TShiftState; X, Y: Integer);

begin

bmbClose.Font.Style := [];

end; //reset font back when mouse move over form

User events and System events OnClick and OnMouseMove initiated by user. ‘System Events’ respond to something happening in the computer without direct action by user. Computer has internal clock which trigger Delphi’s Timer component and event handler. Other system events as OnCreate and OnShow, in form management.

Procedure TfrmSystemTime.tmrSysTimeTimer(Sender: TObject);

begin

lblSysTime.Caption := TimeToStr(time);

end;

TimeToStr function convert Time data type variable to string Timer Interval default value is 1000, changing to 5000 will update timer value every 5th second. OnMouseDown and OnMouseUp procedure TfrmSystemTime.FormMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

tmrSysTime.Enabled := False;

end;

procedure TfrmSystemTime.FormMouseUp(Sender: TObject; Button:

TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

lblSysTime.Caption := TimeToStr(time);

tmrSysTime.Enabled := True;

end;

The ‘form’ system events procedure pnlShowMouseMove(Sender: TObject;

Shift: TShiftState; X, Y: Integer);

procedure FormMouseMove(Sender: TObject;

Shift: TShiftState; X, Y: Integer);

procedure bmbCloseMouseMove(Sender: TObject;

Shift: TShiftState; X, Y: Integer);

Each list contain three groupings: Sender: TObjects;

Shift: TShiftState;

X, Y: Integer;

Name on left of colon (Sender, Shift, X, Y) represent parameter. Delphi makes parameters available in the event handler. Name of right of colon, (TObjects, TShiftStates, Integer), represent data type of corresponding parameters. procedure TfrmMousePos.FormMouseDown(Sender: TObject;

Button: TMouseButton; Shift: TShiftState; X, Y: Integer);

begin

if button = mbLeft then

frmMousePos.Canvas.Rectangle(x-10, y-10, x+10, y+10);

end;

end.

TMousButton can have values mbLeft, mbRight, mbMiddle. TShiftState can have values none, one or more of ssShift, ssAlt, ssCtrl, ssLeft, ssRight, ssMiddle, ssDouble. Show whether any keyboard buttons where held down when OnMouseDown event occurred and whether event was initiated by mouse left, right or middle button or double-click.

Methods and Memo component procedure TfrmMemoDemo.btnClearClick(Sender: TObject);

begin

memDemo.Clear;

memDemo.SetFocus;

end;

procedure TfrmMemoDemo.btnCopyClick(Sender: TObject);

begin

memDemo.CopyToClipboard;

memDemo.SetFocus;

end;

procedure TfrmMemoDemo.btnPasteClick(Sender: TObject);

begin

memDemo.PasteFromClipboard;

memDemo.SetFocus;

end;

procedure TfrmMemoDemo.btnCutClick(Sender: TObject);

begin

memDemo.CutToClipboard;

memDemo.SetFocus;

end;

Several components (eg Memo and Edit) have Clipboard methods (CutToClipboard, CopyToClipboard, PasteFromClipboard).

Methods with constants as parameters Methods just used give single, direct command: Clear, SetFocus, CutToClipboard. When using Canvas, need additional information to method. Following Methods calls (no assignments):

procedure TfrmCanvasMethods.btnTextClick(Sender: TObject);

begin

Canvas.TextOut(40, 15, 'Two rectangles and two ellipses');

end;

procedure TfrmCanvasMethods.btnShapesClick(Sender: TObject);

begin

Canvas.Rectangle(40,40,400,200);

Canvas.Rectangle(80,80,360,160);

Canvas.Ellipse(150,50,290,190);

Canvas.Ellipse(100,100,340,140);

end;

Rectangle(x1, y1, x2, y2); Parameters must be integers, upper left corner (x1,y2) and lower right corner (x2, y2). Top left corner of canvas is (0,0) Ellipse(x1, y1, y2, y2);

Same coordinates as for Rectangle. Ellipse then drawn as largest ellipse to fit in rectangle. Specified bounding box of ellipse. If bounding box is square, ellipse become a circle.

Canvas methods used: Procedure TextOut (X, Y: Integer; const Text: String); Procedure Rectangle(X1, Y1, X2, Y2: Integer); Procedure Ellipse(X1, Y1, X2, Y2: Integer); Additional Notes on Canvas Drawing (not from book): ********************* DrawBtnClick ******************}

procedure TForm1.DrawBtnClick(Sender: TObject);

{Draw some ellipses on the canvas - random size and color}

var

i:integer;

cx,cy:integer;

begin

with image1, canvas do

begin

for i:= 1 to 10 do

begin

cx:=random(width);

cy:=random(height);

brush.color:=random(256*256*256);

ellipse(cx,cy,cx+random(100), cy+random(100));

end;

end;

end;

{******************* ClearBtnClick ****************}

procedure TForm1.ClearBtnClick(Sender: TObject);

{Erase the canvas by drawing a big rectangle}

begin

with image1, canvas do

begin

brush.color:=clwhite;

canvas.rectangle(clientrect);

end;

end;

{***************** SaveBtnClick *******************}

procedure TForm1.SaveBtnClick(Sender: TObject);

{Make a bitmap, copy canavsa to it and save it in a listbox}

var

b:TBitmap;

begin

b:=TBitmap.Create;

b.height:=image1.height;

b.width:=image1.width;

b.canvas.copyrect(rect(0,0,b.width,b.height),image1.canvas,image1.cl

ientrect);

listbox1.items.addobject('Image

#'+inttostr(listbox1.items.count+1),b);

end;

{******************* ListBox1Click *****************}

procedure TForm1.ListBox1Click(Sender: TObject);

{Retrieve bitmap from listbox and copy it to the canvas}

var

b:TBitmap;

begin

if listbox1.itemindex>=0 then

with listbox1 do

begin

b:=TBitmap(items.objects[itemindex]);

image1.Canvas.CopyRect(image1.clientrect,b.canvas,rect(0,0,b.width,b

.height));

end;

end;

{******************** Image1MouseDown **************}

procedure TForm1.Image1MouseDown(Sender: TObject; Button:

TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

with image1.canvas do

begin

pen.width:=3;

pen.color:=clblack;

drawing:=true;

moveto(x,y);

end;

end;

{*************** Image1MouseMove **************}

procedure TForm1.Image1MouseMove(Sender: TObject; Shift:

TShiftState; X,

Y: Integer);

begin

If drawing

then with image1 do

begin

cursor:=crNone; {to keep cursor redraw from erasing part of our

line}

canvas.lineto(x,y);

cursor:=crdefault;

end;

end;

{***************** Image1MouseUp ****************}

procedure TForm1.Image1MouseUp(Sender: TObject; Button:

TMouseButton;

Shift: TShiftState; X, Y: Integer);

begin

drawing:=false;

end;

{******************* Formcreate *************}

procedure TForm1.FormCreate(Sender: TObject);

begin

clearbtnclick(sender); {draw initial rectangle to clear image

canvas}

end;

procedure TForm1.Button1Click(Sender: TObject);

var

b:TBitMap;

begin

If savedialog1.execute

then image1.picture.savetofile(savedialog1.filename);

end;

Procedures and parameters Declaring and defining a method Entire code for entire unit example: 1 unit Unit1;

2 interface

3 uses

4 Windows, Messages, SysUtils, Variants, Classes, Grapgics,

5 Controls, Forms, Dialogs;

6 type

7 TForm1 = class(TForm)

8 Button1: TButton;

9 Procedure Button1Click(Sender: TObject);

10 Private

11 { Private declarations}

12 Public

13 { Public declarations}

14 end;

15 var

16 Form1: TForm1;

17 implementation

18 {$R *.nfm}

19 procedure TFOrm.Button1Click(Sender: TObject);

20 begin

21 Color := clPurple;

22 end;

23 end.

18 {$R *.nfm} – generate a.NET from module

Delphi consists of 3 parts: Name (line1) Interface (lines 2-16) Implementation (lines 17-23) Up to now worked with implementation section. In declaring method also interested in type declaration (lines 6-14). TButton in form, Delphi declared component of type TButton to Button1(line 8) part of TForm1 class (line 7). Also created event handler, procedure called Button1Click, Delphi declared this procedure also as part of TForm1 class (line 9). This procedure, the event handler, is method of TForm class. Definition follows in implementation section (lines 19-22). Note header in method definition (line 19) combines class name, TForm1, and method name, Button1Click and has same parameter list as declaration (line 9). When crate own methods follow Delphi’s example. Declare method’s signature, in private section of form’s type definition, (lines 10-11), and define method in implementation section as defined event handler methods earlier. unit C12e01u;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls, ExtCtrls;

type

TfrmSixpenceJoe = class(TForm)

rgpPoducts: TRadioGroup;

lblCostText: TLabel;

procedure rgpPoductsClick(Sender: TObject);

private

{ Private declarations }

procedure DisplayPrice (Product, Price: String);

public

{ Public declarations }

end;

var

frmSixpenceJoe: TfrmSixpenceJoe;

implementation

{$R *.dfm}

procedure TfrmSixpenceJoe.DisplayPrice(Product, Price: String);

begin

lblCostText.Caption := Product + ' cost R' + price + ' per

kilogram';

end; {proc TfrmSixpenceJoe.DisplayPrice}

procedure TfrmSixpenceJoe.rgpPoductsClick(Sender: TObject);

begin

case rgpPoducts.ItemIndex of //using TRadio Group

0 : displayPrice('Flour', '12.99');

1 : displayPrice('Rice', '4.39');

2 : displayPrice('Sugar', '4.10');

3 : displayPrice('Mealie', '2.16');

end;

end; {procedure TfrmSixpenceJoe.rgpPoductsClick}

end.

Procedures

1) Reduce amount of programming, result shorter ‘simpler’ program 2) Make changing program simpler 3) Less likely to cause errors 4) Lead to library of re-usable procedures that may be useful in future programs

Calling (invoking) a procedure Own procedure similar to writing event handler and calling procedure similar to calling a standard method. When user clicks RadioButton, Delphi calls associated event handler. Event handler code calls procedure DisplayPrice, passing required values for Product and Price string variables as parameters. Procedure call has form: DisplayPrice (‘Flour’, ’12.99);

Can create procedure that does not use parameters. Parameters of call must match header in order, number and type of parameter. General comments on procedures Parameters provide communication between subroutine and surrounding program. Within subroutine parameter has value that can be manipulate like other variable. Unlike local variables declared within subroutine, parameters also have meaning outside subroutine. Points when using procedures:

1) Parameter list of procedure call and procedure definition must mach in respect of type, order and number of parameters.

2) Within procedure, parameter matching is by name, not by order. 3) Procedure that are methods must be declared in class’s type declaration 4) Values send in procedure call van either be constants or variables 5) If procedure is method part of a class, procedure is bound to that class. When define

procedure must explicitly include class name in header.

Components as parameters Extend concept of parameters to include components as parameters unit C12e07u;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;

type

TfrmStudyGroups = class(TForm)

btnNextName: TButton;

gpbGroup: TGroupBox;

lblGroup: TLabel;

lstGroup1: TListBox;

lstGroup2: TListBox;

lstGroup3: TListBox;

lblGroup1: TLabel;

lblGroup2: TLabel;

lblGroup3: TLabel;

procedure btnNextNameClick(Sender: TObject);

private

{ Private declarations }

procedure ShowGroup (GrpNo, Surname: string;

GroupList: TListBox);

public

{ Public declarations }

end;

var

frmStudyGroups: TfrmStudyGroups;

implementation

{$R *.dfm}

procedure TfrmStudyGroups.ShowGroup (GrpNo, Surname: string;

GroupList: TListBox);

{pass component}

begin

lblGroup.Caption := 'Group ' + GrpNo;

gpbGroup.Caption := Surname;

GroupList.Items.Add(Surname); //component TListBox

end; // procedure TfrmStudyGroups.ShowGroup

procedure TfrmStudyGroups.btnNextNameClick(Sender: TObject);

var

Surname: string;

begin

Surname := inputbox('User Input', 'Enter Surname', '');

if surname <> '' then //input box not empty

begin

case upcase(surname[1]) of

'A'..'G' : ShowGroup('1', Surname,lstGroup1);

'H'..'O' : ShowGroup('2', Surname,lstGroup2);

'P'..'Z' : ShowGroup('3', Surname,lstGroup3);

else //first letter not alphabet

lblGroup.Caption := '?'

end; //case

end //if surname

else //User press Cancel or left input box blank

showmessage('No surname provided');

end;

end.

Why and when should we use procedures? When same or similar task more than once. Using methods consolidate program statements connected to particular operation in one place. Good practise to choose name that describes clearly what method does. Comment clearly, include brief comment after method’s header to describe what the method does and role of each parameter. Returning values from a procedure Can write procedure that sends data in other direction, out of procedure to the calling statement. Place the reserved word var in the parameter list in front of the parameter whose value we want to calculate end then send out from the procedure to the calling statement. The Inc(x) procedure Inc() use variable parameters. Inc(x) is same as x := x + 1;

Example of parameter as method to use to provide return value. unit C12e08u;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls, Spin;

type

TfrmFee = class(TForm)

sedTakings: TSpinEdit;

btnFee: TButton;

lblFee: TLabel;

procedure btnFeeClick(Sender: TObject);

private

{ Private declarations }

procedure CalcFee (Takings: integer; var FeeStr: string);

public

{ Public declarations }

end; // end TfrmFee = class(TForm)

var

frmFee: TfrmFee;

implementation

{$R *.dfm}

procedure TfrmFee.CalcFee (Takings: integer; var FeeStr: string);

var

Fee: double;

begin

Fee := Takings * 0.075 + 20; //Calculate fee

FeeStr := 'The fee is ' + FloatToStrF(Fee, ffCurrency, 15, 2)

end; // procedure CalcFee

procedure TfrmFee.btnFeeClick(Sender: TObject);

var

FeeStr: string;

begin

CalcFee(sedTakings.Value, FeeStr); // Proc call: derive string

lblFee.Caption := FeeStr; //display it

end; // procedure TfrmFee.btnFeeClick

end.

CalcFee takes two parameters: Takings, value parameter of type integer, and FeeStr, variable parameter of type string. Reserve word var is immediately before FeeStr in parameter list. Have both variable parameters, declared in the method header and local variables, declared between method header and the begin statement. Parameters provide communication between calling statement and procedure and has value outside the method. Local variables are available only inside a method. TSpeedButton Properties AllowAllUp If allowAllUp is True, all SpeedButtons in group can be unselected. If

False, group acts like group of RadioButtons. Down To select SpeedButton, set Down property to True. GroupIndex SpeedButtons can function independently or in group. If GroupIndex

is zero, it functions independently. If several SpeedButtons have same nonzero value for GroupIndex, they function as a group

Prefix spd... Use Speed buttons often have images on their faces and used with panels to create

toolbars. Can function either independently or in groups. unit C12e09u;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms, Dialogs, Buttons, StdCtrls;

type

TfrmMarkUp = class(TForm)

gpbWholesale: TGroupBox;

gpbMarkUp: TGroupBox;

gpbSelling: TGroupBox;

edtWholesale: TEdit;

lblSelling: TLabel;

spdFifteen: TSpeedButton;

spdTwenty: TSpeedButton;

spdTwentyFive: TSpeedButton;

bmbReset: TBitBtn;

procedure spdFifteenClick(Sender: TObject);

procedure bmbResetClick(Sender: TObject);

procedure spdTwentyClick(Sender: TObject);

procedure spdTwentyFiveClick(Sender: TObject);

private

{ Private declarations }

procedure SellingPrice (Cost: String; Markup: double;

var SellStr: string); // new method

public

{ Public declarations }

end;

var

frmMarkUp: TfrmMarkUp;

implementation

{$R *.dfm}

procedure TfrmMarkUp.SellingPrice (Cost: String; Markup: double;

var SellStr: string); // new method

var

Wholesale, Selling: double;

begin

Wholesale := StrToFloat(Cost);

Selling := Wholesale + Wholesale * Markup; // add markup

SellStr := FloatToStrF(Selling, ffCurrency, 15, 2);

end; // procedure TfrmMarkUp.SellingPrice

procedure TfrmMarkUp.spdFifteenClick(Sender: TObject);

var

SellStr: string;

begin

SellingPrice(edtWholesale.Text, 0.15, SellStr);

lblSelling.Caption := SellStr;

end; // procedure TfrmMarkUp.spdFifteenClick

procedure TfrmMarkUp.spdTwentyClick(Sender: TObject);

var

SellStr: string;

begin

SellingPrice(edtWholesale.Text, 0.2, SellStr);

lblSelling.Caption := SellStr;

end;

procedure TfrmMarkUp.spdTwentyFiveClick(Sender: TObject);

var

SellStr: string;

begin

SellingPrice(edtWholesale.Text, 0.25, SellStr);

lblSelling.Caption := SellStr;

end;

procedure TfrmMarkUp.bmbResetClick(Sender: TObject);

begin

edtWholesale.clear; // clear wholesale price

lblSelling.Caption := ''; //clear selling price

edtWholesale.SetFocus;

spdFifteen.down := false; // setet 15% button

spdTwenty.down := false; // setet 15% button

spdTwentyFive.down := false; // setet 15% button

end;

end.

Constant parameter – restricted version of value parameter since cannot change values. Using where appropriate can limit chance of changing values by mistake. Out parameter – restricted version of variable parameter, can only return value from method and cannot bring value into method the way variable parameter can. Procedure SellingPrice (const Cost: string; const Markup: double;

out SellStr: string);

User Interface Factors Reversibility – reversibility state user should be able to backtrack when choices are made. User should ideally fell free to experiment with interface without being concerned that they will do something wrong that cannot be undone. Conflicting principles – Different user interface design principles may conflict with each other (eg reversibility and economy).

Functions and Exceptions

- Event Handlers = special type of procedure, activated by user-events such as mouse click, but also called by system-events as OnTimer or OnFormShow

- Standard Methods = may be either procedures or functions. Provide capabilities of different types of object (eg Ellipse of Canvas object)

- Standard Subroutines = StrToInt and ShowMessage, may be either procedures or functions

- Programmer-written methods = programmer writes, eg SellingPrice procedure There are similarities between functions and procedure. Also differences: functions designed particularly for doing arithmetic and mathematical operations and supply single value without using variable or out parameters. Functions may be either methods (part of class) or standalone functions. Delphi’s standard functions doing string handling NewValue := StrToInt(‘2468’);

CapitalsStr := UpperCase(‘This is a crazy string’);

Message Dialogs also involve functions If MessageDlg(‘Do you want to exit?’, mtConfirmation,

[bYes, mbNo], 0) = mrYes then

// executed if user clock Yes

Else

// executed if user clicks No

Functions different from procedures, function’s name carries a value. Examples StrToInt ot UpperCase have values assigned to variables, MessageDlg has value that can be tested in IF statement. Procedure names do not carry any values, supply through the VAR and OUT parameters in their parameter list. unit C13e01u;

interface

uses

Windows, Messages, SysUtils, Variants, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls, Buttons;

type

TfrmTax = class(TForm)

gpbSell: TGroupBox;

gpbTax: TGroupBox;

edtSell: TEdit;

lblTax: TLabel;

bmbOK: TBitBtn;

bmbClear: TBitBtn;

procedure bmbOKClick(Sender: TObject);

procedure bmbClearClick(Sender: TObject);

private

{ Private declarations }

function TaxIncl (Selling, Rate: double): double; //added

public

{ Public declarations }

end;

var

frmTax: TfrmTax;

implementation

{$R *.dfm}

function TfrmTax.TaxIncl (Selling, Rate: double): double; //added

begin

Result := (Selling * Rate) + Selling;

end; // function TfrmTax.TaxIncl

procedure TfrmTax.bmbOKClick(Sender: TObject);

const

Rate = 0.14;

var

Selling, Tax: double;

begin

try

Selling := StrToFloat(edtSell.Text); //convert input to double

Tax := TaxIncl(Selling, Rate); // calculate tax via function

lblTax.Caption := FloatToStrF(Tax, ffCurrency, 15,2); //display

except

ShowMessage('Invalid Input');

bmbClear.Click; // Reset interface by 'Clicking' bmbClear

end;

end;

procedure TfrmTax.bmbClearClick(Sender: TObject);

begin

lblTax.Caption := '';

edtSell.Clear;

edtSell.SetFocus;

end; //procedure tFrmTax.bmbClearClick;

end.

General form of function declaration: Function FunctionName (ParameterList): ReturnType;

Use only value or constant parameters to bring values into function. Function calcuolate value of type ReturnType attached to function’s name, and function’s name similar to variable’s name. Heade definition is similar to function declaration except class name attached to front of function name Declaration:

function TaxIncl (Selling, Rate: double): double;

Function header includes name of class: function TfrmTax.TaxIncl (Selling, Rate: double): double;

Delphi create temporary Result variable when a function is called. Use Result to set value calling statement receives when function end. Alternative use function name (TaxIncl) instead of Result: TaxIncl := (Selling * Rate) + Selling;

Enhancing the IF Statements Improve IF statements in some way: Statement: If status = true then

Alternative: If status then

Statement: If validate (A, B, C) = true then

Alternative: If validate (A, B, C) then

Statement: If (Sum > 0) and (Leftover = 0) then

Result := true

Else

Result := false;

Alternative: Result := (Sum > 0) and (Leftover = 0);

Statment: If Validate (A, B, C) = true then

ShowAccessStatus (true)

Else

ShowAccessStatus (false);

Alternative: ShowAccessStatus (Validate (A, B, C));

Differences between functions and procedures Procedure declaration using constant and out parameters: Procedure DoCalc (const InValue: Integer;

out OutValue: Double);

Function declaration: Function OutValue (const InValue: Integer): Double;

Subsequent program steps for procedure: DoCalc(InVal, OutVal);

Function call: OutVal := OutValue(InVal);

If wanted to add 10 to value calculated by subroutine, procedure would be: DoCalc(InVal, OutVal);

Final := OutVal + 10;

Function part of expression: Final := OutValue(InVal) + 10;

Nested Function Calls Advantage of functions is that function is similar to a variable. Procedure TfrmFuncProc.btnDoubleClick(Sender: TObject);

Begin

lblOut.Caption := IntToStr(StrToInt(edtIn.text) * 2);

end; //procedure TfrmFuncProc.btnDoubleClick

First function call StrToInt(edtIn.Text) convert input value to integer. This takes integer value and can be doubled (* 2). Expression after doubling also has value, use as parameter in IntToStr function call. This return string value which can be assigned directly to Label’s Caption.

Exception Handling When exception occurs in subroutine that does not have exception handler, that subroutine terminates and exception return occurs to the calling subroutine. If subroutine has exception handling path, exception is steered through it. If not, subroutine is also abandoned and exception return happens to its calling subroutine and so on. If not include any specific exception handling for particular exception anywhere in program, Delphi calls default exception handler which then display message. Program from example: Procedure TfrmAccess.ReadCode (out A, B, C: integer);

Var

strValue: string;

begin

strValue := edtCode.Text;

C := StrToInt(strValue[3]);

B := StrToInt(strValue[2]);

A := StrToInt(strValue[1]);

End; //procedure TfrmAccess.ReadCode

Procedure TfrmAccess.bmbOKClick(Sender: TObject);

Var

A, B, C: integer;

Begin

ReadCode(A, B, C);

ShowAccessStatus(Validate(A, B, C));

ResetUI;

End; // procedure TfrmAccess.bmbOKClick;

When user enter alphabetic string into edtCode, StrToInt function raises exception. ReadCode is abandoned and execution returns to subroutine call. Because exception not handled it is still alive. bmbOKClick does not have calling routines and Delphi default exception action and display exception message. Accepting three characters only Use RAISE keyword to generate own exception: Procedure TfrmAccess.ReadCode (out A, B, C: integer);

Var

strValue: string;

begin

strValue := edtCode.Text;

if length (strValue) <> 3 then

raise Exception.create (‘Length Invalid’);

C := StrToInt(strValue[3]);

B := StrToInt(strValue[2]);

A := StrToInt(strValue[1]);

End; //procedure TfrmAccess.ReadCode

Must change bmbOKCLick to handle the exception in orderly way and update display accordingly Procedure TfrmAccess.bmbOKClick(Sender: TObject);

Var

A, B, C: integer;

Begin

try

ReadCode(A, B, C);

Except

A := 0;

B := 0;

C := 0;

Showmessage (‘Recovery from an exception’); //test mess

End;

ShowAccessStatus(Validate(A, B, C));

ResetUI;

End; // procedure TfrmAccess.bmbOKClick;

If user enter alphabetic character or code not three digits long, an exception occurs in ReadCode, causing exception return to bmbOKClick. bmbOKClick now has exception handling and execution is not abandoned but continues in the exception handling path. Parameters set to zero and suitable message displayed. Exception can be raised in one place and handled somewhere else. Exception raised either in StrRoInt ot ReadCode procedure but handled in bmbOKClick event handler. The try...finally construction Can be used when finalisation code must be executed irrespective of whether or not exception occurs. Want to ResetUI to run irrespective of whether or not exception occurred. Can wrap a try...finally around a try...except statement: Procedure TfrmAccess.bmbOKCLick(Sender: TObject);

Var

A, B, C: integer;

Begin

Try

Try

readCode(A, B, C);

ShowAccessStatus(Validate(A, B, C));

Except

ShowAccessStatus(false); //force error display

End; //end try...except

Finally

resetUI;

end; // end try...finally

end; // procedure TfrmAccess.bmbOKClick;

IIf axception occurs in call line execution continues which calls ShowAccessStatus with parameter set to false. The end; terminates the try..except section and finally introduces code that runs irrespective of whether exception has occurred or not. Delphi guarantees ResetUI will always run. We give no notification that exception handling has been performed.