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 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 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 NewAdress IsThisWorthy GimmeMoney Something A, B, C Lookout
: : : : : : :
Integer; string; boolean; Currency; variant; char; 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 Max Middle ErrStr MaxAmount
= = = = =
30; 500; (Max + Min) div 2; 'Some errors occured'; 123.45;
SomeValue := Middle + 200;
Variable Types: String String[15] Integer Boolean Char
// Series of characters // Specify maximum length for string // Numbers // True or False // 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 StrToInt StrToFloat FloatToStrF FloatToStr
Convert integer to string Convert string to Integer Convert string to floating-point number Convert floating-point to string and format the string (digits after decimal) 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 True True False False
Value2 True False True False
(Value1 and Value2) True False False False
(Value1 or Value) True True True False
Not(Value1) False False True 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 FALSE and FALSE or FALSE or TRUE
= = =
A and FALSE and FALSE and FALSE
C TRUE //and has precedence over or TRUE //evaluate 1st part (give FALSE) //FALSE or TRUE give result TRUE
(B or C) (FALSE or TRUE
TRUE) //brackets have precedence // evaluate 2nd part (give TRUE) // 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; Result := ‘Pass’;
//if x >= 50 then do nothing //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:
Methods: Use:
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 lines. LoadFromFile – loads lines of text from text file Lines.SaveToFile – Save to file 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: Prefix: Use:
Checked If true a tick appears in box; if false box is empty chk... 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 40, 50, 60 : lblDemo.Caption := ‘Option type 70..99 : lblDemo.Caption := ‘Option type 1..39, 41..49, 51 : lblDemo.Caption := ‘Option type Else lblDemo.Caption := ‘Not in one of the options’; end; end; For Char: ‘A’..’H’ ‘I”..’L’, ‘N’..’P’ ‘M’
: : :
1’; 2’; 3’; 4’;
A to H I to L, then N to P 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) 2) 3) 4) 5)
Delete specific section in string Insert substring into string at given location Get length of string Find position of substring in string 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
2 3
for Variable := Integer Expression to|downto Integer Expression do statement; for Variable := Char Expression to|downto Char Expression do Statement; 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 2
function Random : Extended; 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 int int int int int
next 5 numbers = 35 = 74 = 45 = 50 = 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
Prefix
Item.Count lst...
Gives index of currently selected item in list. Value -1 no item selected Number of items listed in ListBox
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 ItemIndex Items.Count Columns
Events Prefix Use
Contains Captions of RadioButtons appear in group Index of currently RadioButton in RadioGroup. Value is -1 if none Selected Number of RadioButtons in RadioGroup Integer value determine number of columns in which RadioButtons Arranged inside RadioGroup. Default value 1 makes buttons appear in single column Activated if user clicks any RadioButtons in RadioGroup
OnClick rgp... 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 ShiftMove 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 Down GroupIndex
Prefix Use
If allowAllUp is True, all SpeedButtons in group can be unselected. If False, group acts like group of RadioButtons. To select SpeedButton, set Down property to True. 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
spd... 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.