In this version of EuroCC,
we'll replace the Buttons with RadioButtons.
We'll also introduce subroutines, which constitute the power of every real programming language.
As in the previous lessons, let's have a look at what version 2 of EuroCC will become.
There is also another change that you can't see when running the program, but only at "design" time. The number of labels for the results and the names of the currencies has been cut in half. Now, each label shows the amount as well as the currency: we combined the two strings to one new string.
Notice that now the amounts in the labels are nicely aligned, which was not the case in our previous version. We achieve this by replacing the font of the labels with a "fixed width" font, and by making the labels right aligning.
1 Euro equals 40.3399 BEF (Belgian franc). BTW: the conversion rate for
Luxemburg Franc is the same.
1 Euro equals 2.20371 NLG ("Netherlands" Guilder). Netherlands = Dutch.
Clicking the "equals" button should convert the number from the edit-box to a value in Euro (the method of calculation depends from the radiobutton which is selected).
Next, the value is converted from Euro to the other currencies and the results are shown in the labels. The label that corresponds with the starting currency must become invisible.
The program also has to perform a conversion when a radiobutton is clicked. The conversion equally has to be done if a value is entered and the ENTER key is pressed.
The program has to start with a conversion of 100 Euro to the other currencies.
Components for this application, for 3 currencies: 1 edit-box for the input of the amount, 1 button, 3 labels for the results (resulting amounts plus names of currencies).
Edit1
Button1
RadioGroup1
Label1
Label2
Label3
Now you can set the properties for all the labels at once:
In the Editor, Delphi has created a template for this event handler.
Add some code to the event handler as follows:
procedure TForm1.ConvertButtonClick(Sender: TObject);
begin
CurrConvert;
end;
procedure TForm1.ConvertRadioGClick(Sender: TObject); begin CurrConvert; end;
CurrConvert is the name of the procedure that will perform the calculations and that will show the results. Without this routine "CurrConvert", we would have to repeat the entire code in both the event handlers. Later on, we would have to repeat that block of code in a third and in a fourth event handler: one for pressing the ENTER key after the amount is entered, and one for the first "automatic" conversion that has to be done right after the start of the program.
private { Private declarations } procedure CurrConvert;
procedureTForm1.CurrConvert; var Amount, Euro: real; S1: string; begin Amount := StrToFloat(InputEdit.Text); Euro := Amount; S1 := FormatFloat('0.00', Euro); EuroLabel.Caption := S1 + ' Euro'; end;
Of course, this is only a small part of the code that we need. We are not looking at the radiobuttons and we aren't making any conversions. But testing your program in small bits (bites?) will make it a lot easier to spot any errors.
What is the first decision to be made by the program?
Such a decision is made with an if:
if a_condition then an_instruction;
The word then also may be followed by a block of instructions, inserted between the reserved words begin and end. But that's not neccesary in our simple program.
Taking into account that the first radiobutton is button number 0, we could replace the line
Euro := Amount;
with this construction:
if ValutaRadioG.ItemIndex = 0 then
Euro := Amount;
if ValutaRadioG.ItemIndex = 1 then
Euro := Amount / 40.3399;
if ValutaRadioG.ItemIndex = 2 then
Euro := Amount / 2.20371;
Using if... then... else... will improve our code and make it faster (of course,
the increase in speed cannot be measured in this simple example, but speed will
become a lot more important in bigger applications). Thus, our code should be something
like this:
if ValutaRadioG.ItemIndex = 0 then
Euro := Amount
else
calculate_value_in_euro;
Note that no semicolon is allowed after an instruction that precedes an else. The compiler will treat the entire if...then...else as one big instruction.
Also calculate_value_in_euro has to be split in two parts. We need a second if...then...else,
which will be "nested" into the first one:
if ValutaRadioG.ItemIndex = 0 then
Euro := Amount
else
if ValutaRadioG.ItemIndex = 1 then
Euro := Amount / 40.3399
else
Euro := Amount / 2.20371;
The second decision to be made by the program, comes after the calculations are done and the results have been shown:
We could do this with an if...then...else construct. But the code "and the other two labels must be visible" is really awful, because it is repeated 3 times. First solution: make all labels visible and then hide one of them through an if...then...else.
But it can be done a lot simpler, without using any "if"! In order to make a component visible
or invisible, you have to assign a logical (boolean) value to it's "visible" property, TRUE or FALSE.
Or an expression that results in a logical value. Have a look at this chunk of pseudo
code:
EuroLabel.Visible := button_0_is_not_selected;
BEFLabel.Visible := button_1_is_not_selected;
NLGLabel.Visible := button_2_is_not_selected;
{ Convert value in InputEdit to Euro, depending on the radiobutton selected in ValutaRadioG. Next, convert from Euro to other currencies. } procedure TForm1.CurrConvert; var Amount, Euro, BEF, NLG: real; S1, S2, S3: string; begin // Convert text of EDIT to numerical value Amount := StrToFloat(InputEdit.Text); // Calculate value in Euro if ValutaRadioG.ItemIndex = 0 then Euro := Amount else if ValutaRadioG.ItemIndex = 1 then Euro := Amount / 40.3399 else Euro := Amount / 2.20371; // Convert to other currencies BEF := Euro * 40.3399; NLG := Euro * 2.20371; { Convert the floating point values to strings. '0.00' is the "Format String", meaning: 'result must have 2 digits after dec. separator' } S1 := FormatFloat('0.00', Euro); S2 := FormatFloat('0.00', BEF); S3 := FormatFloat('0.00', NLG); { Put strings in the CAPTIONs of the LABELs, followed by the name of the currency. Add spaces in order to have equal lengths. } EuroLabel.Caption := S1 + ' Euro '; BEFLabel.Caption := S2 + ' BEF/LUF'; NLGLabel.Caption := S3 + ' NLG '; { Do not show the label which corresponds with the starting currency } EuroLabel.Visible := (ValutaRadioG.ItemIndex <> 0); BEFLabel.Visible := (ValutaRadioG.ItemIndex <> 1); NLGLabel.Visible := (ValutaRadioG.ItemIndex <> 2); end;
By now it becomes clear why I suggested the font Courier New for the labels: all characters have the same width in this font, also the spaces. As we made the labels right aligning, all the values will align nicely on the form.
Compile your program and test it thoroughly.
Select the form, either in the listbox of the Object Inspector, or by clicking on an empty
spot of Form1. In the Object Inspector, double-click in the field next to OnCreate.
In the code-editor, complete the event handler:
procedure TForm1.FormCreate(Sender: TObject);
begin
CurrConvert;
end;
Easy, isn't it? Go ahead and test if it works.
Select InputEdit. In the Object Inspector, double-click in the field next to OnKeyPress.
Complete the event handler:
procedure TForm1.InputEditKeyPress(Sender: TObject; var Key: Char);
begin
if Key = #13 then ValutaConvert;
end;
Delphi hands the variabele Key to us in the header of the procedure. That variable contains the "character" that corresponds with the key that has been pressed. Delphi wrote: var Key: Char which means that Key is a variable of type "char".
The operator # is used to convert a number to the corresponding character. Thus, #13 means: the character of which the code is 13, the "character" that Windows receives when you press ENTER.
OK, test it!
See you again for lesson 5!
© Copyright 1999
Studiebureau Festraets