home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frostbyte's 1980s DOS Shareware Collection
/
floppyshareware.zip
/
floppyshareware
/
GLEN
/
DDJ1191.ZIP
/
STRUPROG.ASC
< prev
Wrap
Text File
|
1991-10-18
|
12KB
|
389 lines
_STRUCTURED PROGRAMMING COLUMN_
by Jeff Duntemann
[LISTING ONE]
PROGRAM HCalc;
USES App,Dialogs,Objects,Views,Menus,Drivers,
FInput, { By Allen Bauer; on CompuServe BPROGA }
Mortgage; { By Jeff Duntemann; from DDJ 10/91 }
CONST
cmNewMortgage = 199;
cmCloseAll = 198;
cmCloseBC = 197;
cmPrintSummary = 196;
WindowCount : Integer = 0;
TYPE
MortgageDialogData =
RECORD
PrincipalData : Real;
InterestData : Real;
PeriodsData : Integer;
END;
THouseCalcApp =
OBJECT(TApplication)
InitDialog : PDialog; { Dialog for initializing a mortgage }
CONSTRUCTOR Init;
PROCEDURE InitMenuBar; VIRTUAL;
PROCEDURE CloseAll;
PROCEDURE HandleEvent(VAR Event : TEvent); VIRTUAL;
PROCEDURE NewMortgage;
END;
PMortgageTopInterior = ^TMortgageTopInterior;
TMortgageTopInterior =
OBJECT(TView)
Mortgage : PMortgage;
CONSTRUCTOR Init(VAR Bounds : TRect);
PROCEDURE Draw; VIRTUAL;
END;
PMortgageBottomInterior = ^TMortgageBottomInterior;
TMortgageBottomInterior =
OBJECT(TScroller)
{ Points to Mortgage object owned by TMortgageView }
Mortgage : PMortgage;
CONSTRUCTOR Init(VAR Bounds : TRect;
AHScrollBar, AVScrollbar : PScrollBar);
PROCEDURE Draw; VIRTUAL;
END;
PMortgageView = ^TMortgageView;
TMortgageView =
OBJECT(TWindow)
Mortgage : TMortgage;
CONSTRUCTOR Init(VAR Bounds : TRect;
ATitle : TTitleStr;
ANumber : Integer;
InitMortgageData :
MortgageDialogData);
PROCEDURE HandleEvent(Var Event : TEvent); VIRTUAL;
PROCEDURE PrintSummary;
DESTRUCTOR Done; VIRTUAL;
END;
CONST
DefaultMortgageData : MortgageDialogData =
(PrincipalData : 100000;
InterestData : 10.0;
PeriodsData : 360);
{------------------------------}
{ METHODS: THouseCalcApp }
{------------------------------}
CONSTRUCTOR THouseCalcApp.Init;
VAR
R : TRect;
aView : PView;
BEGIN
TApplication.Init; { Always call the parent's constructor first! }
{ Create the dialog for initializing a mortgage: }
R.Assign(20,5,60,16);
InitDialog := New(PDialog,Init(R,'Define Mortgage Parameters'));
WITH InitDialog^ DO
BEGIN
{ First item in the dialog box is input line for principal: }
R.Assign(3,3,13,4);
aView := New(PFInputLine,Init(R,8,DRealSet,DReal,0));
Insert(aView);
R.Assign(2,2,12,3);
Insert(New(PLabel,Init(R,'Principal',aView)));
{ Next is the input line for interest rate: }
R.Assign(17,3,26,4);
aView := New(PFInputLine,Init(R,6,DRealSet,DReal,3));
Insert(aView);
R.Assign(16,2,25,3);
Insert(New(PLabel,Init(R,'Interest',aView)));
R.Assign(26,3,27,4); { Add a static text "%" sign }
Insert(New(PStaticText,Init(R,'%')));
{ Up next is the input line for number of periods: }
R.Assign(31,3,36,4);
aView := New(PFInputLine,Init(R,3,DUnsignedSet,DInteger,0));
Insert(aView);
R.Assign(29,2,37,3);
Insert(New(PLabel,Init(R,'Periods',aView)));
{ These are standard buttons for the OK and Cancel commands: }
R.Assign(8,8,16,10);
Insert(New(PButton,Init(R,'~O~K',cmOK,bfDefault)));
R.Assign(22,8,32,10);
Insert(New(PButton,Init(R,'Cancel',cmCancel,bfNormal)));
END;
END;
{ This method sends out a broadcast message to all views. Only the
{ mortgage windows know how to respond to it, so when cmCloseBC is
{ issued, only the mortgage windows react--by closing. }
PROCEDURE THouseCalcApp.CloseAll;
VAR
Who : Pointer;
BEGIN
Who := Message(Desktop,evBroadcast,cmCloseBC,@Self);
END;
PROCEDURE THouseCalcApp.HandleEvent(VAR Event : TEvent);
BEGIN
TApplication.HandleEvent(Event);
IF Event.What = evCommand THEN
BEGIN
CASE Event.Command OF
cmNewMortgage : NewMortgage;
cmCloseAll : CloseAll;
ELSE
Exit;
END; { CASE }
ClearEvent(Event);
END;
END;
PROCEDURE THouseCalcApp.NewMortgage;
VAR
Code : Integer;
R : TRect;
Control : Word;
ThisMortgage : PMortgageView;
InitMortgageData : MortgageDialogData;
BEGIN
{ First we need a dialog to get the intial mortgage values from }
{ the user. The dialog appears *before* the mortgage window! }
WITH InitMortgageData DO
BEGIN
PrincipalData := 100000;
InterestData := 10.0;
PeriodsData := 360;
END;
InitDialog^.SetData(InitMortgageData);
Control := Desktop^.ExecView(InitDialog);
IF Control <> cmCancel THEN { Create a new mortgage object: }
BEGIN
R.Assign(5,5,45,20);
Inc(WindowCount);
{ Get data from the initial mortgage dialog: }
InitDialog^.GetData(InitMortgageData);
{ Call the constructor for the mortgage window: }
ThisMortgage :=
New(PMortgageView,Init(R,'Mortgage',WindowCount,
InitMortgageData));
{ Insert the mortgage window into the desktop: }
Desktop^.Insert(ThisMortgage);
END;
END;
PROCEDURE THouseCalcApp.InitMenuBar;
VAR
R : TRect;
BEGIN
GetExtent(R);
R.B.Y := R.A.Y + 1; { Define 1-line menu bar }
MenuBar := New(PMenuBar,Init(R,NewMenu(
NewSubMenu('~M~ortgage',hcNoContext,NewMenu(
NewItem('~N~ew','F6',kbF6,cmNewMortgage,hcNoContext,
NewItem('~C~lose all','F7',kbF7,cmCloseAll,hcNoContext,
NIL))),
NIL)
)));
END;
{---------------------------------}
{ METHODS: TMortgageTopInterior }
{---------------------------------}
CONSTRUCTOR TMortgageTopInterior.Init(VAR Bounds : TRect);
BEGIN
TView.Init(Bounds); { Call ancestor's constructor }
END;
PROCEDURE TMortgageTopInterior.Draw;
VAR
YRun : Integer;
Color : Byte;
B : TDrawBuffer;
STemp : String[20];
BEGIN
Color := GetColor(1);
MoveChar(B,' ',Color,Size.X); { Clear the buffer to spaces }
MoveStr(B,' Principal Interest Periods',Color);
WriteLine(0,0,Size.X,1,B);
MoveChar(B,' ',Color,Size.X); { Clear the buffer to spaces }
{ Here we convert payment data to strings for display: }
Str(Mortgage^.Principal:7:2,STemp);
MoveStr(B[2],STemp,Color); { At beginning of buffer B }
Str(Mortgage^.Interest*100:7:2,STemp);
MoveStr(B[14],STemp,Color); { At position 11 of buffer B }
Str(Mortgage^.Periods:4,STemp);
MoveStr(B[27],STemp,Color); { At position 23 of buffer B }
WriteLine(0,1,Size.X,1,B);
MoveChar(B,' ',Color,Size.X); { Clear the buffer to spaces }
WriteLine(0,2,Size.X,1,B);
MoveChar(B,' ',Color,Size.X); { Clear the buffer to spaces }
MoveStr(B,'Paymt # Int. Prin. Balance',Color);
WriteLine(0,3,Size.X,1,B);
END;
{------------------------------------}
{ METHODS: TMortgageBottomInterior }
{------------------------------------}
CONSTRUCTOR TMortgageBottomInterior.Init(VAR Bounds : TRect;
AHScrollBar, AVScrollBar :
PScrollBar);
BEGIN
TScroller.Init(Bounds,AHScrollBar,AVScrollBar);
GrowMode := gfGrowHiX + gfGrowHiY;
Options := Options OR ofFramed;
END;
PROCEDURE TMortgageBottomInterior.Draw;
VAR
Color : Byte;
B : TDrawBuffer;
YRun : Integer;
STemp : String[20];
BEGIN
Color := GetColor(1);
FOR YRun := 0 TO Size.Y-1 DO
BEGIN
MoveChar(B,' ',Color,Size.X); { Clear the buffer to spaces }
Str(Delta.Y+YRun+1:4,STemp);
MoveStr(B,STemp+':',Color); { At beginning of buffer B }
{ Here we convert payment data to strings for display: }
Str(Mortgage^.Payments^[Delta.Y+YRun+1].PayPrincipal:7:2,STemp);
MoveStr(B[6],STemp,Color); { At beginning of buffer B }
Str(Mortgage^.Payments^[Delta.Y+YRun+1].PayInterest:7:2,STemp);
MoveStr(B[15],STemp,Color); { At position 11 of buffer B }
Str(Mortgage^.Payments^[Delta.Y+YRun+1].Balance:10:2,STemp);
MoveStr(B[24],STemp,Color); { At position 23 of buffer B }
WriteLine(0,YRun,Size.X,1,B);
END;
END;
{------------------------------}
{ METHODS: TMortgageView }
{------------------------------}
CONSTRUCTOR TMortgageView.Init(VAR Bounds : TRect;
ATitle : TTitleStr;
ANumber : Integer;
InitMortgageData :
MortgageDialogData);
VAR
TopInterior : PMortgageTopInterior;
BottomInterior : PMortgageBottomInterior;
HScrollBar,VScrollBar : PScrollBar;
R,S : TRect;
BEGIN
TWindow.Init(Bounds,ATitle,ANumber); { Call ancestor's constructor }
{ Call the Mortgage object's constructor using dialog data: }
WITH InitMortgageData DO
Mortgage.Init(PrincipalData,
InterestData / 100,
PeriodsData,
12);
{ Here we set up a window with *two* interiors, one scrollable, one }
{ static. It's all in the way that you define the bounds, mostly: }
GetClipRect(Bounds); { Get bounds for interior of view }
Bounds.Grow(-1,-1); { Shrink those bounds by 1 for both X & Y }
{ Define a rectangle to embrace the upper of the two interiors: }
R.Assign(Bounds.A.X,Bounds.A.Y,Bounds.B.X,Bounds.A.Y+4);
TopInterior := New(PMortgageTopInterior,Init(R));
TopInterior^.Mortgage := @Mortgage;
Insert(TopInterior);
{ Define a rectangle to embrace the lower of two interiors: }
R.Assign(Bounds.A.X,Bounds.A.Y+5,Bounds.B.X,Bounds.B.Y);
{ Create scroll bars for both mouse & keyboard input: }
VScrollBar := StandardScrollBar(sbVertical + sbHandleKeyboard);
{ We have to adjust vertical bar to fit bottom interior: }
VScrollBar^.Origin.Y := R.A.Y; { Adjust top Y value }
VScrollBar^.Size.Y := R.B.Y - R.A.Y; { Adjust size }
{ The horizontal scroll bar, on the other hand, is standard: }
HScrollBar := StandardScrollBar(sbHorizontal + sbHandleKeyboard);
{ Create bottom interior object with scroll bars: }
BottomInterior :=
New(PMortgageBottomInterior,Init(R,HScrollBar,VScrollBar));
{ Make copy of pointer to mortgage object: }
BottomInterior^.Mortgage := @Mortgage;
{ Set the limits for the scroll bars: }
BottomInterior^.SetLimit(80,InitMortgageData.PeriodsData);
{ Insert the interior into the window: }
Insert(BottomInterior);
END;
PROCEDURE TMortgageView.HandleEvent(Var Event : TEvent);
BEGIN
TWindow.HandleEvent(Event);
IF Event.What = evCommand THEN
BEGIN
CASE Event.Command OF
cmPrintSummary : PrintSummary;
ELSE
Exit;
END; { CASE }
ClearEvent(Event);
END
ELSE
IF Event.What = evBroadcast THEN
CASE Event.Command OF
cmCloseBC : Done
END; { CASE }
END;
PROCEDURE TMortgageView.PrintSummary;
BEGIN
END;
DESTRUCTOR TMortgageView.Done;
BEGIN
Mortgage.Done; { Dispose of the mortgage object's memory }
TWindow.Done; { Call parent's destructor to dispose of window }
END;
{ MAIN PROGRAM OBJECT DECLARE & RUN: }
VAR
HouseCalc : THouseCalcApp;
BEGIN
HouseCalc.Init;
HouseCalc.Run;
HouseCalc.Done;
END.