Science makes it known,
Engineering makes it work,
Art makes it beautiful.
|
|
Lazarus Sub-form, Grid Cell Background Color, StringGrid Cell Editor, and
Calling FORTRAN
(Includes Downloads)
A Lazarus sub-form is a form shown/used/called by a higher
level form using the sub-form's
ShowModal method (calls sub-form's FormShow(...)). The
ShowModal method transfers
exclusive control to the sub-form.
This page looks at part of an actual Lazarus application (MRmain)
using sub-forms (both use
TStringGrids; one changes the cell background color to
red on an error condition, the other uses
a simple StringGrid
cbsEllipsis Editor Style). One calls procedures in
external Librarys.1
untBT10
/
FrmBT10
and
missle14
/
FrmPayload
are two sub-forms in a Lazarus multiform
application to input and
analyze a model rocket design. These two units/forms are used
to input/modify/review body tube
(or fuselage segment) data for
a model rocket. Both use units
NumRecGlbl.pas
(requires include files
genetyp.inc and nrtyp.inc - see
Lazarus calling FORTRAN
for more information) and
MRcommon.pas
(requires include file missle.inc, calls procedures in
Object Pascal Library
missle02.dll)
for global data and common procedures.
Form
Missle10
(see footnote 2 on that page) is another sub-form used by MRmain.
Above:
Sub-form BorderIcons Properties
Recommend disabling the sub-form window minimize
and exit buttons.
Right:
StringGrid Options
Recommended for editing cells
Suggestion:
On the sub-form TLCLComponent (or any descendent)
that closes the form, in Object Inspector set
Property ModalResult (if available) to
mrNone.
In the TLCLComponent's event procedure, set
ModalResult:=mrClose;
|
|
TLCLComponent can be a TButton, TMenuItem,
etc. Avoid using TForm.Close - it will set
ModalResult:=mrCancel;
|
Simplified exploded view of
single stage rocket with
conical nose, two body tubes,
one conical boattail, and
four fins
Stage 1, Body Tube 1 can be
used as a Payload Section.
Couplers (not shown) are
used to join nose, body tubes,
and conical transitions together.
|
For each stage, body tubes are numbered in sequence from stage upper edge
or nose tip.
For a consistent User Interface, both sub-forms display
body tube sequence, body tube length, and
body tube radius in a TStringGrid. Each
TStringGrid row represents a body tube.
Body tube sequence number is temporarily stored in NumRecGlbl
variable iData[ ].
Body tube length, body tube radius, body tube mass, body tube
cross-sectional area, and body tube surface area are stored in
MRcommon
two dimensional arrays (matrices)2; MRcommon
variable nbt[ ] is the number of body tubes per stage array.
Cells are right justified using TStringGridPrepareCanvas.
Cells' text are edited using TStringGridSetEditText to allow editing
of each cell when entered; recommended method.
Setting ModalResult to a non-zero value closes sub-form; this
application uses mrClose to indicate error free close.
untBT10 / FrmBT10
Unit untBT10.pas3 contains several procedures that are not
members of Class (TFrmBT10); procedure name is not prefixed
with class name. These procedures can access instance FrmBT10
variables; however, the variable name must be prefixed with the
instance name. See procedure sortBT ( ) below for an
example.
'Quick and dirty' demonstration of changing StringGrid Cell background
color to Red when an error occurs; a Lazarus Sub-form in an actual
application; and calling FORTRAN .dll subprograms via an Object
Pascal .dll.
After using the form shown in
Lazarus Tabsheets
to enter the basic design parameters, untBT10 / FrmBT10
(shown at right overlaying the main form MRmain)
initializes the body tube data and allows the user to verify/adjust
body tube sequence (only partially visible in screenshot at right; column 1),
length, diameter, and optionally mass for each stage.
When length and diameter for each body tube on all stages
have been entered with no errors,
body tube cross-sectional and surface area is calculated using procedure
BTarea (...) in missle02.dll (declaration
shown below right; calls
FORTRAN FUNCTION SRCYLNDR (...) in
mathproc.dll 4).
By changing the body tube sequence number, it is possible to move body
tubes around.
If TFrmBT10.BTstrngGridSetEditText(...) detects an
error, it highlights the cell in red; requiring a
TFrmBT10.BTstrngGridDrawCell(...) procedure.
Added
three variables to TFrmBT10 public (shown at right):
selectedCol (currently edited column),
selectedRow (currently edited row), and
colorCellRed (true when error occurred, false otherwise).
When TFrmBT10.BTstrngGridSetEditText(...) detects an
error, it :
calls BTsgError (...) (not shown; download source untBT10.pas,
link above) to process the error;
BTsgError (...) invokes FrmBT10.BTstrngGrid.Repaint;
FrmBT10.BTstrngGrid.Repaint triggers
TFrmBT10.BTstrngGridDrawCell(...).
TFrmBT10.BTstrngGridDrawCell(...) is invoked
whenever the grid cell is drawn; hence the code at right will "reset"
the grid cell color to white when the cell is re-entered
and
colorCellRed = false.
When the user selects another stage OR clicks the Sort button
OR clicks the Close button,
AND stage number of body
tubes > 1, sub-form re-sequences the stage body tube matrices with
procedure sortBT ( ).5
Procedure sortBT ( ) sets boolean variable indxd to
true since the index table iData[ ] contains
body tube sequence numbers,
then for each body tube matrix:
moves the current stage body tube matrix column to
NumRecGlbl array variable rData[ ];
calls
nrlazrs
Object Pascal procedure indxSort (...) 6 to
re-sequence rData[ ];
moves rData[ ] to current stage body tube matrix column.
Close button:
closes sub-form and transfers control back to higher level form by setting
ModalResult to a non-zero value.
Higher level form shows sub-form with:
ModalResult:=FrmBT10.ShowModal;
Lazarus application glider01 (boost/glider,
rocket/glider, lifting body, and Rogallo flexwing design data
input) also uses untBT10 / FrmBT10. Rocket/gliders,
lifting bodies, and Rogallo flexwings may use body tube(s)
|
|
missle14 / FrmPayload
Unit missle14.pas contains several procedures that are not
members of Class (TFrmPayload).
A 'quick and dirty' demonstration of using StringGrid cbsEllipsis
Editor Style and another example of a Lazarus Sub-form
in an actual application.
After using untBT10 / FrmBT10 to finalize the body tube data,
missle14 / FrmPayload (shown at right overlaying
MRmain) is used to select one of
Stage 1's body tubes for the payload section (if any).
A payload section is used to contain cameras, radio transmitters, scientific
instruments or experiments, etc., during flight.
StringGrids use cell editors to change the content of cells. Will be
using the grid's EditorByStyle method for selecting a body tube for
the payload section. The
simplest, generic Editor Style to use here is cbsEllipsis,
which is a simple button, to be placed in column one ("Select BT") of the
sub-form's StringGrid (btStringGrid).
Clicking in column one ("Select BT") triggers
TFrmPayload.btStringGridSelectEditor(...), causing a button to appear
in the editing cell.
Clicking on the button invokes
TFrmPayload.btStringGridEditButtonClick(...), which
then loads the selected body tube data into the Payload Section
data. User may then optionally adjust payload section coupler internal
lengths and specify payload mass.
TFrmPayload.btStringGridSetEditText(...) cancels any text changes
the user may make to btStringGrid.
Delete button:
Sets Payload Section data to zero.
Close button:
closes sub-form and transfers control back to higher level form by setting
ModalResult to a non-zero value.
Higher level form shows sub-form with:
ModalResult:=FrmPayload.ShowModal;
|
|
1. The projects on this website employs software reuse
extensively; this page builds on other pages on this website.
External FORTRAN FUNCTIONS/SUBROUTINES are declared the same way as an
Object Pascal external function/procedure, with correct
arguments and return type; refer to Free Pascal Programmer's Guide
Chapter 12, Programming shared libraries and
Variable Storage Compatibility and Equivalency.
Have found when a Lazarus program's event procedure directly calls a
FORTRAN subprogram, it may produce an Access Violation Exception
when the event procedure exits, even though no calculation errors
occurred. This exception does not occur when called via a Free Pascal
Library function/procedure.
2. Each column of the body tube (or fuselage segment) matrices
stores the values of all the body tubes being used in the current stage.
3. untBT10 / FrmBT10 is also being used in a Lazarus
application to input and analyze
Rocket/Glider
and other glider designs
(Rocket/Glider and
Lifting Body
fuselages can be similar to model rockets). The glider modifications
require untBT10 uses unit
missle18
and constant ModelRocket.
missle18
/ FrmFinShpArea
is used to input fin/wing/stabilizer measurements and shape for
both model rockets and gliders. Boost/Glider, Rocket/Glider, and Lifting Body
specific data are defined in missle18 { public declarations }.
4. Several
mathproc.dll
subprograms are available for download at
tir33.for subprograms.
FORTRAN uses the stdcall calling convention. Unlike Pascal,
by default FORTRAN subprograms expects their arguments to be passed
by reference.
5. Had two choices at this point - use proven procedures/SUBROUTINES
(would require moving each body tube matrix column to a sort
space, re-sequence the sort space, move sort space back to body tube
matrix column) OR develop new procedures/SUBROUTINES
specifically for the body tube matrix datatype
(BodyTubeData). Selected the first choice (use proven
procedures/SUBROUTINES,
use NumRecGlbl variable rData[ ] for sort space);
this method had been used/tested in Missle11 / Missle10 for
sorting conical transitions
matrices by Length Nose Tip to Conical Transition; see procedure
sortCTstage (...) in unit MRcommon.
6. indxSort (...) calls FORTRAN SUBROUTINEs RSORT3 (...) and
SAVECOPY (...) in
sttstcs.dll. In
this application, RSORT3 (...) is not
used - body tube matrix columns are already indexed by iData[ ].
The Pascal arrays are passed as a fixed size array datatype, most of
the FORTRAN subprograms use variable bounds dimensioning.
Fixed size array datatypes defined in include files genetyp.inc,
nrtyp.inc, and missle.inc.
SAVECOPY (...) external declaration in nrlazrs.pas
RC, IORDER are defined as fixed size array datatypes
|
SAVECOPY (...) subroutine header in sttstcs.for
R, IORDER are dimensioned with variable bounds - argument
N2 is the number of elements
|
FORTRAN matrices must be explicitly (statically)
dimensioned - can not use variable bounds dimensioning.
This approach has been successfully used in both D and
Free Pascal programs; it may be possible this approach was
a contributing factor
to the Lazarus Access Violation Exception mentioned above.
|