Example 8.4 RAD chaining
We have on several occasions looked at the RAD code that Delphi generates and used that as a guideline in generating our own code. How does the RAD user interface code measure up to the principles above?To assess, this, well model the local bulk magazine stores cash register through two user interface objects and look at their encapsulation. The one form captures the weight of magazines in kilograms and gives the total price when the Calculate button is clicked while the second allows the price per kilogram to be entered, edited and displayed.
The price per kilogram is entered, edited and displayed on a separate form. Both forms are on display at the same time so that the user can switch between them as needed.
Ex 8.4 step 1 The secondary form
Start a new application and add a second form to it. Construct the second form, and initialise edtPriceKg.Text to a suitable value, say 11.99, in the Object Inspector.Ex 8.4 step 2 The main RAD form
The main RAD form, frmCashRegister, is attached to the following unit (unit1):unit CashRegisterU;The main form frmCashRegister uses the secondary form, frmBlkMags , via its associated unit BlkMagsU. This allows it to access directly the value of the Text property of edtPriceKg on the secondary form frmBulkMags, so breaking frmBulkMags encapsulation.
// Accesses a constituent of the other user
// interface object through chaining.
interface
uses
Windows, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, Buttons, StdCtrls;
type
TfrmCashRegister = class(TForm)
gpbWeightKg: TGroupBox;
edtWeightKg: TEdit;
gpbTotalPrice: TGroupBox;
btnCalculate: TButton;
bmbReset: TBitBtn;
lblTotalPrice: TLabel;
procedure btnCalculateClick(Sender: TObject) ;
procedure bmbResetClick(Sender: TObject) ;
procedure FormShow(Sender: TObject) ;
end;
var
frmCashRegister: TfrmCashRegister;
implementation
// specifies the other form, frmBulkMags
uses BulkMagsU;
{$R *.dfm}
procedure TfrmCashRegister.btnCalculateClick(Sender: TObject) ;
var
PriceKg, NoOfKgs, TotalPrice: double;
begin
// Access constituent of other object directly!
PriceKg := StrToFloat(frmBulkMags.edtPriceKg.Text) ; // problem!!??
NoOfKgs := StrToFloat (edtWeightKg.Text) ;
TotalPrice := PriceKg * NoOfKgs;
lblTotalPrice.Caption := FloatToStrF(TotalPrice,ffCurrency,10,2) ;
end;
procedure TfrmCashRegister.FormShow(Sender: TObject) ;
begin
frmBulkMags.Show;
end;
procedure TfrmCashRegister.bmbResetClick(Sender: TObject) ;
begin
edtWeightKg.Text := '';
lblTotalPrice.Caption := '';
edtWeightKg.SetFocus;
end;
end.
Here we see a compromise in the RAD generated code. To allow all the objects on the form to be manipulated through the Object Inspector they must have published visibility. Published visibility is wider even than public visibility and so any object on a user interface form is completely accessible to all other units through the chaining.
Unit CashRegisterU needs to access only edtPriceKgs Text property, but it can also change or read any other property of any other component, and so could, for example, change edtPriceKgs Top property, or disable it or hide it. Is there any way around this?
The next example shows one approach to encapsulating objects on the interface and providing access methods to manipulate them.


