Rapid Development with APL+Win 3.6 Objects
by
Eric Lescasse
APL+Win 3.5
has introduced the possibility for a developer to create his own objects and
use them through the WI system function. Once you’ve
developed your own object with APL+Win, you may use it exactly as if it were
part of the APL+Win system.
This is a
very powerful feature of APL+Win which leads to develop applications in a
complete Object Oriented fashion, thus benefiting from all advantages of Object
Oriented Programming.
One of the
most important features of Object Oriented Programming is to maximize “code
reuse” possibilities.
For all
these reasons, I have spent a great deal of my last 2 years time in developing
a library of reusable objects. This
library has evolved into a product simply entitled “APL+Win 3.6 Objects”. Release 2 of this product is now available.
This paper
will show some of “APL+Win 3.6 Objects”, demonstrate how to use them to quickly
develop great looking APL+Win applications with a minimum of efforts
One of the basic principles adopted when developing APL+Win 3.6 Objects has
been to create reusable objects. This
led to adopt the following principle: an object should be a unique APL function
with no subroutines. This function
should contain APL code for all object properties, methods and event
handlers. An exception to this rule is that
Assembler routines from the ASMFNS workspace are occasionally used, just because
they are assumed to be part of almost any APL application.
All objects
in APL+Win 3.6 Objects are functions and they all start with the letter T. Here are a few example: TForm, TObject, TWebBrowser,
TODBC, TDate, TExcel, TEmail, …
APL+Win 3.6
Objects work with pixel coordinates.
All properties referring to positions and sizes are expressed in pixels.
The APL+Win
3.6 Objects workspace name is OBJECTS.W3
APL+Win 3.6
Objects are declared to the APL+Win system by a function called Classes
which is automatically run (LX) when the OBJECTS.W3 workspace is loaded.
You may
query the Properties method and the Methods method to get a list
of all user defined properties and methods pertaining to an APL+Win 3.6 Object.
Example:
'ff'wi'Create' 'TForm'
ff
'ff'wi'Properties'
caption escape font gaps margins modalresult
'ff'wi'Methods'
Document
All objects
properties and methods are documented and the documentation may be obtained by
prefixing the property or method name with a question mark.
Example:
'ff'wi'?modalresult'
Determines how the form
was closed (read-only property)
Syntax: boolean'object'wi'modalresult'
boolean: 1 if OK button
was clicked (or Enter was pressed), 0 in all other cases
'ff'wi'?Document'
Document the form by
displaying control names within each control
Syntax: 'object'wi'Document'
You may
also get an example of how to use an object by running the TDoc object Help
method on your object.
Example:
'hh'wi'Create'
'TDoc'
hh
'hh'wi'Help'
'TNavigator'
0 0½'ff'wi'Create'
'TForm'('*caption' 'TNavigator Example')
0
0½'ff.nav1'wi'Create' 'TNavigator'('wherelc'Ð Ð Ð Ð)
'ff'wi'Show'
Note that
the hh instance of the TDoc object is automatically created when
you run Classes.
So you only need enter the above second expression.
If you want
to run the example instead of returning its code to the APL session, invoke the
Exec method instead:
'hh'wi'Exec'
'TNavigator'

If you want
to both execute the example and see the corresponding source code in the APL
session, run the ExecHelp method:
0 0½'ff'wi'Create'
'TForm'('*caption' 'TNavigator Example')
0
0½'ff.nav1'wi'Create' 'TNavigator'('wherelc'Ð Ð Ð Ð)
'ff'wi'Show'

Forms
(sometimes called, guess what:
“Windows”) are at the center of most Windows applications and are still
a pain to develop in any language, but particularly in APL+Win which lacks a
good and powerful form editor.
Let’s see
how forms may be developed with “APL+Win 3.6 Objects” Release 2.
)load objects
C:\APLWIN36\OBJECTS SAVED 11/17/1999 18:29:11
In APL+Win
you would create a form the following way:
'ff'wi'Create' 'Form'
ff
and the
form would be centered on the screen and be half the screen height and width.
You may use
the where property to position your form where you want on the screen
and give it the size you want. However
it quickly becomes more difficult to do such things as right justify your form
on the screen or horizontally center it between the right edge of another form
and the right screen edge, etc.
So APL+Win
3.6 Objects contains a TForm object and TForm has a wherelc
property available to further help more easily position your form on the
screen.
The wherelc
property, which is also available for almost all visual objects in “APL+Win 3.6
Objects”, is similar to the standard where property except for the
following:
So let’s
create to small form of 200 by 300 pixels and center it on the screen:
'ff'wi'Create' 'TForm'('wherelc'Ð Ð 200 300)'*Show'

Note the
first 2 arguments of the wherelc property: just like for the where property, the first argument
specifies the top position of the form: an empty vector means “vertically
center the form in the screen”.
Likewise the second empty numeric vector means “horizontally center
the form in the screen”.
Also note
the use of the Show method which is prefixed with a *. The * tells the APL+Win system to use
the standard APL+Win Form object Show method and not any Show
method built into the TForm object.
Now let’s
create several other form objects and position them at various screen
locations:
'ff'wi'Create' 'TForm'('wherelc' Ð Ð 200
300)('ontop'1)'*Show'
'f1'wi'Create' 'TForm'('wherelc' '>' Ð 200
300)('ontop'1)'*Show'
'f1'wi'Create' 'TForm'('wherelc' '>' Ð 200
300)('ontop'1)'*Show'
'f2'wi'Create' 'TForm'('wherelc' '>' '>'200
300)('ontop'1)'*Show'
'f3'wi'Create' 'TForm'('wherelc' Ð '>' 200
300)('ontop'1)'*Show'
'f4'wi'Create' 'TForm'('wherelc' 0 '>' 200
300)('ontop'1)'*Show'
'f5'wi'Create' 'TForm'('wherelc' Ð '>' 200
300)('ontop'1)'*Show'
'f6'wi'Create' 'TForm'('wherelc' '>' 0 200
300)('ontop'1)'*Show'

The '>' notation means “bottom align” or
“right align” the form on the screen, depending on the wherelc argument
used. Note that these alignments are
using the screen workarea and not the screen itself, thus the forms
bottom align with the top of the Windows Task Bar and not with the absolute
bottom of the screen.
Note the
use of the TForm ontop property to ensure that all forms will stay on
top of the APL session.
If you
wanted a form of 100 pixels high but of half the width of the screen you would
write:
'ff'wi'Create' 'TForm'('wherelc' Ð Ð 100 Ð)'*Show'
An empty
vector for the 4th wherelc argument means “half the screen
width”: similarly an empty vector for the 3rd wherelc
argument means “half the screen height”.
Here are a
few other examples:
Create a
form gg just below form ff with same height as ff and
default width (half the screen width)
'gg'wi'Create' 'TForm'('wherelc' '>ff' Ð '=ff' Ð)'*Show'
Create a
form hh below gg but adjust position further down by 10 pixels (5th
wherelc argument)
'hh'wi'Create' 'TForm'('wherelc' '>gg' Ð '=gg' Ð
10)'*Show'
Create a
form ii with same top position and height as ff, 10 pixels to the
right of form ff
'ii'wi'Create'
'TForm'('wherelc' '=ff' '>ff' '=ff'100 0 10)'*Show'
Create a
form jj with same top position as ff, horizontally centered
between left screen edge and left of form ff, 100 pixels wide:
'jj'wi'Create' 'TForm'('wherelc' '=ff' '#<ff' '=ff'
100)('*Show')
Create a
form kk vertically centered between form ii and bottom of screen,
100 pixels wide:
'kk'wi'Create' 'TForm'('wherelc' '>#ii' '=ii' '=ff'
100)('*Show')

Assuming
there is a form called form2 and that you apply the wherelc
property to form1, wherelc arguments have the following meaning
for forms:
|
1st
wherelc argument |
|
|
N |
N pixels
from top of screen |
|
Ð or '<>' |
vertically
center in the screen |
|
'>' |
bottom
align form with the screen |
|
'>form2' |
position
form1 below form2 |
|
'=form2' |
top align
form1 with form2 |
|
'#<form2' |
center
form1 between top of screen and top of form2 |
|
'>#form2' |
center
form1 between bottom of form2 and bottom of screen |
|
'<>form2' |
vertically
center form1 on form2 |
|
2nd
wherelc argument |
|
|
N |
N pixels
from left of screen |
|
Ð or '<>' |
horizontally
center in the screen |
|
'>' |
right
align form with the screen |
|
'>form2' |
position
form1 to the right of form2 |
|
'=form2' |
left
align form1 with form2 |
|
'#<form2' |
center
form1 between left of screen and left of form2 |
|
'>#form2' |
center
form1 between right of form2 and right of screen |
|
'<>form2' |
horizontally
center form1 on form2 |
|
3rd
wherelc argument |
|
|
N |
N pixels
heigh |
|
Ð |
half
screen height |
|
'=form2' |
same
height as form2 |
|
4th
wherelc argument |
|
|
N |
N pixels
width |
|
Ð |
half
screen width |
|
'=form2' |
left
align form1 with form2 |
|
5th
wherelc argument |
|
|
N |
adjust
vertical position by N pixels (positive or negative) |
|
6th
wherelc argument |
|
|
N |
adjust
horizontal position by N pixels (positive or negative) |
|
7th
wherelc argument |
|
|
N |
adjust
form1 height by N pixels (positive or negative) |
|
8th
wherelc argument |
|
|
N |
adjust
form1 width by N pixels (positive or negative) |
Occasionally
you need to center a form on another form.
You can do it using the '<>form' argument:
'ff'wi'Create'
'TForm'('wherelc' 140 500 300 500)('ontop'1)'*Show'
'gg'wi'Create'
'TForm'('wherelc' '<>ff' '<>ff' 100 100)('ontop'1)'*Show'

Once your
form is well sized and positioned on the screen, you want to add controls to
it.
With
APL+Win 3.6 Objects you use the wherelc property to position controls on
your form.
Generally
you set control positions by reference to other controls or to the form using wherelc
argument possibilities. Thus, you only
need to specify the pixels position of the first control.
The wherelc
property allows to quickly design “perfect forms” with virtually no effort.
Most importantly, forms designed with wherelc are extremely easy to
maintain and to change, even if you need to perform drastic changes on them.
TForm objects have a margins
property which you set by specifying the top, left, bottom and right margins
separating form edges and controls you place on the form.
By default
the margins property is set to 5 5 5 5.
TForm objects have a gaps property
which represents the default vertical and horizontal distance in pixels
separating controls on your form.
By default
the gaps property is set to 5 5.
All APL+Win
standard visual objects (Check, Edit, Option, Button,
List, Combo, etc.) have a counterpart object in “APL+Win 3.6
Objects” named the same but with a T prefix (TCheck, TEdit,
TOption, TButton, TList, TCombo, etc.). Only the T objects understand the wherelc
property.
Here are
the possibilities for the wherelc property as far as “APL+Win 3.6
Objects” are concerned (assuming the object you are positioning with wherelc
is called control1 and that there is another object called control2 on the
form):
|
1st
wherelc argument |
|
|
N |
N pixels
from top of form |
|
Ð or '<>' |
place
control1 at top margin from top of form |
|
'>' |
position
control1 at a vertical gap distance below reference control |
|
'=' |
top align
control1 with the reference control |
|
'<' |
place
control1 at bottom margin from bottom of form |
|
'°' |
leave top
position unchanged |
|
'<>' |
vertically
center control1 in form (or frame) |
|
'<>ct2 ct3' |
vertically
center control1, ct2 and ct3 in the form |
|
'>control2' |
position
control1 below control2 using the vertical gap |
|
'=control2' |
top align
control1 with control2 |
|
'>>control2' |
bottom
align with control2 |
|
'#<' |
vertically
center control1 between top of form and top of reference control |
|
'>#' |
vertically
center control1 between bottom of reference control and bottom of form |
|
2nd
wherelc argument |
|
|
N |
N pixels
from left of form |
|
Ð or '<>' |
place
control1 at left margin from left of form |
|
'>' |
position
control1 at an horizontal gap distance below reference control |
|
'=' |
left
align control1 with the reference control |
|
'<' |
place
control1 at right margin from right of form |
|
'°' |
leave
left position unchanged |
|
'<>' |
horizontally
center control1 in form (or frame) |
|
'<>ct2 ct3' |
horizontally
center control1, ct2 and ct3 in the form |
|
'>control2' |
position
control1 to the right of control2 using the horizontal gap |
|
'=control2' |
left
align control1 with control2 |
|
'#<' |
horizontally
center control1 between left of form and left of reference control |
|
'>#' |
horizontally
center control1 between right of reference control and right of form |
|
3rd
wherelc argument |
|
|
N |
N pixels
heigh |
|
Ð |
default
height (height of a combo in current font) |
|
'=' |
same
height as reference control |
|
'=control2' |
same
height as control2 |
|
'>' |
use
remaining space to bottom of form minus bottom margin |
|
'>>' |
use
remaining space to bottom of form |
|
'>N' |
set
height as N pixels and resizes form |
|
'>>N' |
set
height as N pixels and resizes form with no bottom and right margins |
|
'>>control2' |
bottom
align with control2 |
|
'°' |
leave
height unchanged |
|
4th
wherelc argument |
|
|
N |
N pixels
wide |
|
Ð |
default
width (depends on control class) |
|
'=' |
same
width as reference control |
|
'=control2' |
same
width as control2 |
|
'>' |
use
remaining space to right of form minus right margin |
|
'>>' |
use
remaining space to right of form |
|
'>N' |
set width
to N pixels and resizes form |
|
'>>N' |
set width
to N pixels and resizes form with no bottom and right margins |
|
'>>control2' |
right
align with control2 |
|
'°' |
leave
width unchanged |
|
'#N' |
define
width as N times a digit character width in the current font |
|
'@N' |
define
width as N times the largest character width in the current font |
|
'#N' |
define
width as N times an average character width in the current font |
|
5th
wherelc argument |
|
|
N |
adjust
vertical position by N pixels (positive or negative) |
|
6th
wherelc argument |
|
|
N |
adjust
horizontal position by N pixels (positive or negative) |
|
'>label' |
adjust
horizontal position by the label width in pixels |
|
7th
wherelc argument |
|
|
N |
adjust
control1 height by N pixels (positive or negative) |
|
8th
wherelc argument |
|
|
N |
adjust
control1 width by N pixels (positive or negative) |
When you
use the wherelc property, the control on which you apply it becomes the Reference
Control. When installing a new
control, if you use a wherelc
argument like '>' you
indicate that you want to place this new control after the Reference Control.
Example:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

The '>' as 1st wherelc
argument, means “place this control below the previous one”. The '=' as the 2nd wherelc
argument, means “place this control at the same horizontal position as the
previous one” (i.e. left align this control with the previous one). Ð as the 3rd argument
means “use the default height for this control”.
Note that TEdit
objects have a caption property which allows to define the label to the
left of the TEdit control. This text is always right aligned by default
and ends at 5 pixels from the Edit field.
It is always vertically aligned with the text you can type in the Edit
field.
You may
also want to install the Age field to the right of the Name field. In this case you must change the Reference
Control (ff.ed2) when using the wherelc property on ff.ed3,
so that the positioning refers to ff.ed1 (the Name field) instead of the
ff.ed2.
'ff'wi'Create'
'TForm'
'ff.ed1'wi'Create'
'TEdit'('wherelc'Ð 100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 100)
('caption' 'First Name')
'ff.ed3'wi'Create'
'TEdit'('wherelc' '=ff.ed1'
'>' Ð '=' 0 '>10+Age')
('caption' 'Age')
'ff.ed4'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

A slight
change in the line creating ff.ed3 has completely transformed the
form. You may have noticed that the Age
field width is twice as large in this example than in the previous one. This is because once you redefine the Reference
Control with ‘=ff.ed1’ , the Reference Control immediately becomes ff.ed1
and therefore specifying a width for ff.ed3 as '=' means: use the same width as ff.ed1. In the first example ff.ed3 was using
the same width as ff.ed2 which was the Reference Control.
In order to
keep the right width for the ff.ed3 (Age) field, it is necessary to
again change the Reference Control within the ff.ed3 wherelc
property:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)
('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'=ff.ed1' '>' Ð '=ff.ed2'
0 '>10+Age')
('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

On the line
creating ff.ed3 we are adjusting the horizontal position of ff.ed3
by '>10+Age' pixels.
This means
in fact by 10 pixels + the width of label ‘Age’ in the current font.
If we had
not done this adjustment, here is what we would have got:
'ff'wi'Create'
'TForm'
'ff.ed1'wi'Create'
'TEdit'('wherelc'Ð 100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 100)
('caption' 'First Name')
'ff.ed3'wi'Create'
'TEdit'('wherelc' '=ff.ed1' '>' Ð '=ff.ed2')
('caption' 'Age')
'ff.ed4'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

and the Age
caption would be hidden below the ff.ed1 Edit control.
Note that
controls are automatically separated by the vertical and horizontal gaps
defined in the TForm gaps property and that they are distant from
the form edges by the margins defined in the TForm margins
property.
Let’s
change the margins and Show the form again:
'ff'wi'Create'
'TForm'('margins'20 20 20
20)
'ff.ed1'wi'Create'
'TEdit'('wherelc'Ð 100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 100)
('caption' 'First Name')
'ff.ed3'wi'Create'
'TEdit'('wherelc' '=ff.ed1' '>' Ð '=ff.ed2')
('caption' 'Age')
'ff.ed4'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

and now set
the vertical gap to 10 and the horizontal gap to 20.
'ff'wi'Create'
'TForm'('margins'20 20 20 20)('gaps'10
40)
'ff.ed1'wi'Create'
'TEdit'('wherelc'Ð 100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 100)
('caption' 'First Name')
'ff.ed3'wi'Create'
'TEdit'('wherelc' '=ff.ed1' '>' Ð '=ff.ed2')
('caption' 'Age')
'ff.ed4'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

The text
you type in the TEdit input field is vertically aligned with the TEdit
field caption:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
('*text'
'Lescasse')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
('*text'
'Eric')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
('*text'
'France')
'ff'wi'Show'

By default
the TEdit caption property right aligns the label which is
attached to the Edit field.
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff'wi'Show'

You may
however prefer to left align these labels.
In order to do so, use the 'just' 'left' property.
'ff'wi'Create'
'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð 100 Ð 200)('caption' 'Name' ('just' 'left'¯90)
'ff.ed2'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 100)
('caption' 'First Name')('just' 'left'¯90)
'ff.ed3'wi'Create'
'TEdit'('wherelc' '>' '=' Ð '=')
('caption' 'Age')('just' 'left'¯90)
'ff.ed4'wi'Create'
'TEdit'('wherelc' '>' '=' Ð 200)
('caption' 'Country')('just' 'left'¯90)
'ff'wi'Show'
The ¯90
means to start the label at 90 pixels to the left of the Edit fields.

By default
you may press the Escape key to close the form. Try it:
'ff'wi'Create' 'TForm' '*Show'
Press
Esc. This closes the form.
You may however use the escape property to inhibit this behaviour.
Now create the form as follows:
'ff'wi'Create' 'TForm'('escape'0)'*Show'
Press
Esc. This has no effect.
Imagine we
would like an OK button and a Cancel button to be placed on the right of the
form. We would do it the following way,
using 2 new APL+Win 3.6 Objects: TOKButton and TCancelButton:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create' 'TOKButton'('wherelc' '=ff.ed1' '>' Ð Ð)
'ff.bnCancel'wi'Create' 'TCancelButton'('wherelc' '>' '=' '='
'=')
'ff'wi'Show'

However you
might prefer to have the 2 buttons placed a little more to the right of the
form so that they are further away from the Name Edit field. This can easily be done using the 6th
wherelc parameter, as follows:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '>' Ð Ð 0 50)
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' '=' '=')
'ff'wi'Show'

If you
invoke the standard APL+Win Show method on your TForm object, the TForm
object will be displayed with the size it currently had at its creation time
(or when you last resized it with the where, wherelc, extent
or size properties). This may result in a form being too large for the
controls it contains.
Example:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '>' Ð Ð 0 50)
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' '=' '=')
'ff'wi'*Show'

You may at
any time use the TForm Redim method to resize the form to its
minimal size which still shows all controls.
Example:
'ff'wi'Redim'

The Redim
method helps keep a form as small as possible while still displaying all its
controls.
When you
apply the Show or Wait methods on a TForm object, the
following actions take place:
This
ensures that your form is correctly sized to just display all controls it
contains without extra space, that it is then centered on the screen.
Once you
have already set a number of controls on a TForm, and maybe given a
precise size to the TForm, you may want to right justify some controls
on this TForm.
This is
different from the previous example where you cannot govern the size of your
form because it was determined by the Redim method.
In the
following example we are setting the form size to 200 450 pixels, so
that the final form has this exact size and then indicate with '<' that the OK button must be right
justified.
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)
'ff.bnCancel'wi'Create' 'TCancelButton'('wherelc'
'>' '=' '=' '=')
'ff'wi'*Show'

Let’s
assume that we want to add an instance of the new APL+Win Grid object
below the Country field and that we want the Grid to use all the
remaining form space.
This can be
done using '>' as the 3rd
and 4th wherelc arguments.
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' '=' '=')
'ff.grid'wi'Create' 'TGrid'('border'1)('wherelc' '>ff.ed4' Ð
'>' '>')
'ff.grid'wi'Set'('GridRows'20)('GridCols'20)
'ff'wi'*Show'

When using '>' a margin is left between the object
and the form edges. Now let’s assume
you do not want any margin. Simply use '>>' as the wherelc 3rd
and 4th arguments and 0 as the wherelc 2nd
argument:
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' '=' '=')
'ff.grid'wi'Create'
'TGrid'('border'1)('wherelc' '>ff.ed4' 0 '>>' '>>')
'ff.grid'wi'Set'('GridRows'20)('GridCols'20)
'ff'wi'*Show'

Finally
let’s assume that you want to use a TGrid of 200 by 500
pixels. You might do this as follows:
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð 100
Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' '=' '=')
'ff.grid'wi'Create'
'TGrid'('border'1)('wherelc' '>ff.ed4' 0 '>>200' '>>500')
'ff.grid'wi'Set'('GridRows'20)('GridCols'20)
'ff'wi'*Show'

In that
case forcing the TGrid to be 200 by 500 pixels extends the
TForm size and the buttons are no longer right justified in the
form. How could we solve this problem?
In order to
right justify the OK and Cancel buttons in the form again, we would need to
change their horizontal position in the form, but keep the 3 other wherelc
arguments unchanged.
This is
easily done by using '°' for wherelc arguments which need to stay unchanged.
'ff.bnOk'wi'wherelc'
'°' '<' '°' '°'
'ff.bnCancel'wi'wherelc'
'°' '<' '°' '°'

Remember
that '<' as the 2nd wherelc argument means: “right
justify the control in the form”.
Another
technique for right justifying the OK and Cancel buttons would have been to
attach them the right form edge.
All visual
controls in APL+Win 3.5 Objects have an attach property.
Through
this property you tell to each edge of the form each edge of your control is
attached. Form edges are numbered as follows:
1 = left
edge
2 = top
edge
3 = right
edge
4 = bottom
edge
Thus if we
wanted our OK button to be attached to the right edge of the form, we would
like its attach property be defined as:
('attach'3 2 3 2)
This means:
The left OK
button edge is attached to the right form edge (3)
The top OK
button edge is attached to the top of the form (2)
The right
OK button edge is attached to the right form edge (3)
The bottom
OK button edge is attached to the top of the form (2)
Thus when
the form is resized and the form width increased, the OK button stays right
justified!
So we could
have defined the form as follows:
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)('attach'3 2 3 2)
'ff.bnCancel'wi'Create' 'TCancelButton'('wherelc' '>' '<'Ð Ð)('attach'3 2 3 2)
'ff.grid'wi'Create'
'TGrid'('border'1)('wherelc' '>ff.ed4' 0 '>>200' '>>500')
'ff.grid'wi'Set'('GridRows'20)('GridCols'20)
'ff'wi'*Show'

If we
resize the form increasing its height and width, here is what now happens:

The 2
buttons stay attached to the right form edge.
Of course, this
last form is not so nice looking and we would have preferred the TGrid
to be nicely resized as well as the input fields, maybe.
We would
like the TGrid to stay attached to all 4 edges of the form so we will
use the following attach property: ('attach'1
2 3 4). This means:
The left
Grid edge is attached to the left form edge (1)
The top
Grid edge is attached to the top of the form (2)
The right
Grid edge is attached to the right form edge (3)
The bottom
Grid edge is attached to the top of the form (4)
Here is the
result:
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)('attach'3 2 3 2)
'ff.bnCancel'wi'Create' 'TCancelButton'('wherelc'
'>' '<'Ð Ð )('attach'3 2 3 2)
'ff.grid'wi'Create'
'TGrid'('border'1)('wherelc' '>ff.ed4' 0 '>>200' '>>500')
'ff.grid'wi'Set'('GridRows'20)('GridCols'20)('attach'1 2 3 4)
'ff'wi'*Show'

Much better
indeed!
If we
wanted to have the edit controls extend horizontally with the form, we should
have used: ('attach'1 2 3 2)
and the result would have been:
The final
instructions for the form being:
'ff'wi'Create' 'TForm'('*size'200 450)
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed1'wi'attach'1 2 3 2
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed2'wi'attach'1 2 3 2
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed3'wi'attach'1 2 3 2
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.ed4'wi'attach'1 2 3 2
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '<' Ð Ð)('attach'3 2 3 2)
'ff.bnCancel'wi'Create' 'TCancelButton'('wherelc' '>' '<'Ð Ð )('attach'3 2 3 2)
'ff.grid'wi'Create'
'TGrid'('border'1)('wherelc' '>ff.ed4' 0 '>>200' '>>500')
'ff.grid'wi'Set'('GridRows'20)('GridCols'20)('attach'1
2 3 4)
'ff'wi'*Show'

In order to
center a control in a form, you use '<>' as the 2nd wherelc element.
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc' '>'
'=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' '<>'
Ð Ð)
'ff'wi'Show'

Of course
it would have been better to move the button a little further down, say by 12
pixels. This is easily done adding a 5th
element of 12 to its wherelc property:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' '<>' Ð Ð 12)
'ff'wi'Show'

Note that
if the form is resizable, the button is always kept centered on the form, even
with no attach property defined for it.
Let’s resize the form.

If you
wanted the button to stay attached to the bottom of the form when it is
resized, you could however use the attach property. It does not conflict with the automatic
button centering process.
Example:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' '<>' Ð Ð 12)('attach'1 4 1 4)
'ff'wi'Show'

A more
difficult task is to center several controls on the same line on the form. Let’s assume you want an OK button, a Cancel button and a Retry button centered
at the bottom of your form. The way to
specify this is to use any default horizontal position for the first 2 buttons
and to use '<>ff.bnOK ff.bnCancel ff.bnRetry' as the wherelc 2nd
argument for the last button.
Example:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' Ð Ð Ð 12)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '=' Ð Ð Ð)('*caption' 'Retry')
'ff.bnCancel'wi'Create' 'TCancelButton'
('wherelc' '=' '<>ff.bnOk ff.bnRetry ff.bnCancel' Ð Ð)
'ff'wi'Show'
Here is the
result after resizing the form a bit: all 3 buttons stay automatically centered
at the bottom of the form!

What if you
wanted to use a wider separation between the buttons?
You may
simply add an horizontal position increment (6th wherelc
argument) on all 3 buttons:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' Ð Ð Ð 12 20)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '=' Ð Ð Ð 0 20)('*caption' 'Retry')
'ff.bnCancel'wi'Create' 'TCancelButton'
('wherelc' '=' '<>ff.bnOk ff.bnRetry
ff.bnCancel' Ð Ð 0 20)
'ff'wi'Show'

The Redim
method applies a limitwhere property on the form which is resized, so
that the user may not resize this form to a smaller size than the one set by
the Redim method.
Assume you
have placed an object like a TFOne object (a Formula One grid) in the
lower half of a form and an TOKButton and TCancelButton button
right justified in the upper right corner of the form. Now you want to place a TWebBrowser
(an Internet Explorer object) in the upper left corner of you form and you want
it to use all the available space above the TFOne object and to the left
of your buttons.
Here is how
you can develop your form using wherelc:
'ff'wi'Create' 'TForm'
'ff.ss'wi'Create' 'TFOne'('wherelc'200 Ð
'>200' '>500')('border'1)
'ff.ok'wi'Create' 'TOKButton'('wherelc' Ð '<'
Ð Ð)
'ff.cc'wi'Create' 'TCancelButton'('wherelc'
'>' '=' Ð Ð)
'ff.wb'wi'Create' 'TWebBrowser'('wherelc'Ð Ð
'>ff.ss' '>ff.ok')
'ff.wb'wi'Navigate' 'C:\WINNT\Web\wum.htm'
'ff'wi'Show'

Note the
use of '>ff.ss' which quite naturally tells the
object to extend itself down up to the grid object and of the '>ff.ok' which tells the TWebBrowser object to extend itself horizontally
up to the buttons.
If we
wanted all form controls to nicely resize as the form is resized we could add
the following attach properties to each object:
'ff.ss'wi'attach'1 4 3 4
'ff.ok'wi'attach'3 2 3 2
'ff.cc'wi'attach'3 2 3 2
'ff.wb'wi'attach'1 2 3 4
Let’s now
resize the form:

The wherelc
property also allows you to define a control size in terms of the maximum
number of characters allowed in the control.
In order to
do this, you specify the wherelc 4th argument as follows:
&L N
@L N
#L N
where L
is the maximum number of characters allowed in the field and N is the
number of characters on which the control width should be based.
The &
prefix means that the width calculus should be based on average character width
in the control font.
The @
prefix means that the width calculus should be based on the largest character
width in the control font.
The #
prefix means that the width calculus should be based on digits character width
in the control font.
Example:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc' Ð Ð Ð
'&10')
'ff.ed2'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '&10 14')
'ff.ed3'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '@10')
'ff.ed4'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '@10 14')
'ff.ed5'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '#10')
'ff.ed6'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '#10 14')
'ff'wi'Show'

The 3rd
field (ff.ed3) width for example is set the accept 10
W’s which is the largest character in the alphabet. Note that there is an additional 23
pixels added to the found width so that this TEdit control may align
perfectly with a TCombo having the same width definition:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc' Ð Ð Ð
'&10')
'ff.ed2'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '&10 14')
'ff.ed3'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '@10')
'ff.cb1'wi'Create'
'TCombo'('wherelc' '>' '=' Ð '@10')
'ff.ed4'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '@10 14')
'ff.ed5'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '#10')
'ff.ed6'wi'Create' 'TEdit'('wherelc' '>' '='
Ð '#10 14')
'ff'wi'Show'

As you see,
exactly 10 W’s fit in the TCombo and therefore it was
advisable to add some extra space to the TEdit control for it to align
properly with the TCombo.
When
developing APL+Win applications it is very useful to print a copy of your form
with the name of all the controls it contains printed on it.
The Document
method of the TForm object allows you to do that.
Here is an
example:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' Ð Ð Ð 12)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '=' Ð Ð Ð)('*caption' 'Retry')
'ff.bnCancel'wi'Create' 'TCancelButton'
('wherelc' '=' '<>ff.bnOk ff.bnRetry
ff.bnCancel' Ð Ð)
'ff'wi'Show'

'ff'wi'Document'

Note that
when your mouse cursor hovers any control the full control name is displayed in
a tooltip window.
Printing
this form document by pressing Alt+PrtSc and copying it into MS Word,
then sending to printer is a great help when writing your event handlers since
you always have your control names visually available!
One of the
main advantages of using the wherelc property is to be able to extremely
easily maintain and change forms design with virtually no effort.
Assume your
customer asks you to move the Country field before the Age
field: all you have to do is to copy
the line of code creating the ff.ed4 TEdit control (the Country
field) and paste it before the ff.ed3 TEdit control (the Age
field). Here is what you get:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed4'wi'Create' 'TEdit'('wherelc' '>' '=' Ð 200)('caption'
'Country')
'ff.ed3'wi'Create' 'TEdit'('wherelc' '>' '=' Ð '=')('caption'
'Age')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '>' Ð Ð Ð 12)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '=' Ð Ð Ð)('*caption' 'Retry')
'ff.bnCancel'wi'Create' 'TCancelButton'
('wherelc' '=' '<>ff.bnOk ff.bnRetry ff.bnCancel' Ð Ð)
'ff'wi'Show'

Now assume
your customer wants you to move the 3 buttons to the top right of the form, one
below the other. I have highlighted the
changes you need to make to the previous form definition to perform these
changes:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
100 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1'
'>' Ð Ð 0 12)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '>'
'=' Ð Ð)('*caption' 'Retry')
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>'
'=' Ð Ð)
'ff'wi'Show'
With a
little habit, this takes less than 10 seconds and the form now looks like this:

Now assume
your customer asks you to move all the TEdit controls and their labels 40
pixels to the left. I have highlighted
the change you need to make to the form definition to perform this change. It takes less than 5 seconds.
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption'
'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.bnOk'wi'Create'
'TOKButton'('wherelc' '=ff.ed1' '>' Ð Ð 0 12)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '>' '=' Ð Ð)('*caption' 'Retry')
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' Ð Ð)
'ff'wi'Show'

Now move
the 3 buttons 100 pixels to the right:
'ff'wi'Create' 'TForm'
'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð
60 Ð 200)('caption' 'Name')
'ff.ed2'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 100)('caption' 'First Name')
'ff.ed4'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
'ff.ed3'wi'Create' 'TEdit'('wherelc'
'>' '=' Ð '=')('caption' 'Age')
'ff.bnOk'wi'Create' 'TOKButton'('wherelc'
'=ff.ed1' '>' Ð Ð 0 112)
'ff.bnRetry'wi'Create'
'TButton'('wherelc' '>' '=' Ð Ð)('*caption' 'Retry')
'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' Ð Ð)
'ff'wi'Show'
There is
just one character to add to the function definition to perform this last
change!

These are
very simple examples, but when having to deal with complex forms having lots of
controls, the time spared in interface design may be tremendous. Moreover, because the computer is
calculating all control positions for you, the forms you build with wherelc
are almost invariably perfect.
When you
develop a new form you may like to write a simple easy to type function and
progressively add the lines which create the form you want. For example you might want to write a tt
function as follows:
tt;wself
[1] wself'ff'wi'Create' 'TForm'
[2] wself'ff.ed1'wi'Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[3] wself'ff.ed2'wi'Create' 'TEdit'('wherelc' '>'
'=' Ð 100)('caption' 'First Name')
[4] wself'ff.ed4'wi'Create' 'TEdit'('wherelc' '>'
'=' Ð 200)('caption' 'Country')
[5] wself'ff.ed3'wi'Create' 'TEdit'('wherelc' '>'
'=' Ð '=')('caption' 'Age')
[6] wself'ff.bnOk'wi'Create' 'TOKButton'('wherelc'
'=ff.ed1' '>' Ð Ð 0 112)
[7] wself'ff.bnRetry'wi'Create' 'TButton'('wherelc'
'>' '=' Ð Ð)('*caption' 'Retry')
[8] wself'ff.bnCancel'wi'Create'
'TCancelButton'('wherelc' '>' '=' Ð Ð)
[9] 'ff'wi'Show'
However, it
is recommended to use relative naming when adding controls to your form and to
write the function as follows, for reasons which will become clearer in the
next paragraph:
tt;Z;wself
[1] wself'ff'wi'Create' 'TForm'
[2] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[3] Zwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð
100)('caption' 'First Name')
[4] Zwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð
200)('caption' 'Country')
[5] Zwi'.ed3.Create' 'TEdit'('wherelc' '>' '=' Ð
'=')('caption' 'Age')
[6] Zwi'.bnOk.Create' 'TOKButton'('wherelc' '=ff.ed1'
'>' Ð Ð 0 112)
[7] Zwi'.bnRetry.Create' 'TButton'('wherelc' '>' '=' Ð
Ð)('*caption' 'Retry')
[8] Zwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>'
'=' Ð Ð)
[9] Zwi'Show'
Not only is
this last function a little quicker to write, but it also is a little more
readable. It will also greatly help you
transform your small function into a new object for your GUI interface.
It is
recommended to develop your forms as new objects in the system. It is very simple to do this.
There is a
template object in the OBJECTS.W3 workspace called TFormClass.
Here is its
code:
A TFormClass
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;io;wself
[1] © A TFormClass B -- TFormClass Template Object
[2] © Use this template to create any new class based on a TForm
object
[3] © Replace TFormClass by the new class name everywhere in
this function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ... argumentN
[9] © (c)2000 Eric Lescasse[11jul00]
[10]
[11] io1
[12] :if 2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'TFormClass"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] :case'Action'
[20] :selectwarg
[21] :case'class'
[22] wres'TFormClass'
[23]
[24] ©-------------------------------------------©
Template property and Method
[25] © The lines below are provided to help you
easily add properties and/or methods
[26] © to you object. Do as follows:
[27] © 1. select the whole property or method
section below
[28] © 2. copy paste it elsewhere under the
:case'Action' section
[29] © 3. change the word 'property' to you
property name
[30] © or
the word 'Method' to your method name
[31] © 4. adapt the :case'?property' or
:cas'?Method' documentation
[32] © 5. write the necessary specific code under
the © Add lines below ... comment
[33] ©-------------------------------------------©
sample property
[34] :case'?property'
[35] wres"Description"
[36] wreswres,tcnl,"Syntax: 'object'wi'property'{value}"
[37] wreswres,tcnl,"value: value
description"
[38] wreswres,tcnl,"Example:
'object'wi'property'..."
[39] :case'property'
[40] :if 1=½warg
[41] wreswi'*property'
[42] :else
[43] C2warg
[44] wi'*property'C
[45] :end
[46] ©-------------------------------------------©
sample method
[47] :case'?Method'
[48] wres'Description'
[49] wreswres,tcnl,"Syntax: 'object'wi'Method'{param1}{param2}..."
[50] wreswres,tcnl,"param1: parameter 1 description"
[51] wreswres,tcnl,"param2:
parameter 2 description"
[52] wreswres,tcnl,"Example:
'object'wi'Method'..."
[53] :case'Method'
[54]
[55] :else
[56] wreswi'*'
[57] :end
[58] :else
[59] error'Unknown TFormClass command: ',B
[60] :end
If you want
to create a form as a new User Defined object, edit the TFormClass
function and do the following:
And here
you go you’re ready to use your new form as an object.
I have
defined the last example used in this document as a T_MyForm class. Here is the code I obtained:
A T_MyForm
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;io;wself
[1] © A T_MyForm B -- T_MyForm Template Object
[2] © Use this template to create any new class based on a TForm
object
[3] © Replace T_MyForm by the new class name everywhere in this
function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ... argumentN
[9] © (c)2000 Eric Lescasse[11jul00]
[10]
[11] io1
[12] :if 2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'T_MyForm"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] Zwi'.ed1.Create'
'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')
[20] Zwi'.ed2.Create'
'TEdit'('wherelc' '>' '=' Ð 100)('caption' 'First Name')
[21] Zwi'.ed4.Create' 'TEdit'('wherelc'
'>' '=' Ð 200)('caption' 'Country')
[22] Zwi'.ed5.Create'
'TEdit'('wherelc' '>' '=' Ð '=')('caption' 'Age')
[23] Zwi'.bnOk.Create'
'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)
[24] Zwi'.bnRetry.Create' 'TButton'('wherelc'
'>' '=' Ð Ð)('*caption' 'Retry')
[25] Zwi'.bnCancel.Create'
'TCancelButton'('wherelc' '>' '=' Ð Ð)
[26]
[27] :case'Action'
[28] :selectwarg
[29] :case'class'
[30] wres'T_MyForm'
[31]
[32] ©-------------------------------------------©
Template property and Method
[33] © The lines below are provided to help you
easily add properties and/or methods
[34] © to you object. Do as follows:
[35] © 1. select the whole property or method
section below
[36] © 2. copy paste it elsewhere under the
:case'Action' section
[37] © 3. change the word 'property' to you
property name
[38] © or
the word 'Method' to your method name
[39] © 4. adapt the :case'?property' or
:cas'?Method' documentation
[40] © 5. write the necessary specific code under
the © Add lines below ... comment
[41] ©-------------------------------------------©
sample property
[42] :case'?property'
[43] wres"Description"
[44] wreswres,tcnl,"Syntax:
'object'wi'property'{value}"
[45] wreswres,tcnl,"value: value
description"
[46] wreswres,tcnl,"Example:
'object'wi'property'..."
[47] :case'property'
[48] :if 1=½warg
[49] wreswi'*property'
[50] :else
[51] C2warg
[52] wi'*property'C
[53] :end
[54] ©-------------------------------------------©
sample method
[55] :case'?Method'
[56] wres'Description'
[57] wreswres,tcnl,"Syntax: 'object'wi'Method'{param1}{param2}..."
[58] wreswres,tcnl,"param1: parameter 1 description"
[59] wreswres,tcnl,"param2: parameter 2 description"
[60] wreswres,tcnl,"Example: 'object'wi'Method'..."
[61] :case'Method'
[62]
[63] :else
[64] wreswi'*'
[65] :end
[66] :else
[67] error'Unknown T_MyForm command: ',B
[68] :end
and now to
use the new object, assuming you have modified the Classes function and
run it as described above:
'ff'wi'Create'
'T_MyForm' 'Show'
or:
'ff'wi'Create'
'T_MyForm' 'Wait'

Note that TFormClass
is a template function and contains sample code to create a property and/or a
method to your object. These are lines 32
to 62 in T_MyForm. We
will see how to use these template property and method later on. However to make this document smaller we
will temporarily remove lines 32 to 62 from later T_MyForm
function listings.
TForm and TMDIForm objects have a Show
and a Wait method which invoke the Redim method and then center
the form on the screen before showing it.
Therefore
the Show and Wait methods may change your form size and location
on the screen.
If you just
want to show your form or wait on it, you may want to use the *Show or *Wait
methods which neither move the form nor resize it.
Up to now
we have seen how to easily design forms.
Now we need to see how data can be collected from the forms.
To isolate
the developer from having to cope with APL+Win properties, methods and events
the following scheme has been adopted.
Save
initial data in an APL variable, use the aplname property to associate
this APL variable with the control to which it should correspond. When the form is closed, the APL variable is
automatically updated with whatever data has been entered in the control.
Note that
you usually want to use the Wait (or *Wait) method rather than
the Show (or *Show) method to display your form as a modal form
so that your program stops running and waits on the form until it is
closed.
Example
Consider
the following function (We have highlighted the instructions necessary to
collect data from this sample form):
Rtt10;Z;NAME;wself
[1] NAME'Eric'
[2] wself'ff'wi'Create' 'TForm'
[3] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð Ð)('caption'
'Name')
[4] Zwi'.ed1.aplname' 'NAME'
[5] Zwi'.bnOK.Create' 'TOKButton'('wherelc' '=' '>' Ð Ð
0 20)
[6] Zwi'Wait'
[7] RNAME
Let’s call
it:
tt10

Now enter
Lescasse into the edit field and press Enter (or click OK):

The
function returns:
Lescasse
as you
press Enter or Click OK.
It is
important to return information from a form so that we may know how the form
was closed. Did the user press the Esc
key or clicked the Cancel button to discard user input or did he press Enter
or clicked the OK button to collect user input?
The TForm
object has a modalresult property which returns 1 if and only if
a TOKButton has been clicked (or if Enter was pressed) to close
the form.
We could
therefore change our tt10 function to a tt11 function reading as
follows:
Rtt11;Z;NAME;wself
[1] NAME'Eric'
[2] wself'ff'wi'Create' 'TForm'
[3] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð Ð)('caption'
'Name')
[4] Zwi'.ed1.aplname' 'NAME'
[5] Zwi'.bnOK.Create' 'TOKButton'('wherelc' '=' '>' Ð Ð
0 20)
[6] Zwi'Wait'
[7] R(wi'modalresult')NAME
When we run
this function, if we press Enter or click OK to close the form we
get the following result:
tt11
1 Eric
If on the
other hand we press the Esc key or click the form close or Cancel
button we get:
tt11
0 Eric
Note that
the modalresult property does only work if you add a TOKButton to
your TForm.
Tip: if you do not want a TOKButton to
appear on your form, you may still add such a button to your form but set its wherelc
property to some negative position like:
'wherelc' ¯100 ¯100 Ð Ð
Here is how
you should write an application to call the T_MyForm object and collect
data input.
Rtt12;NAME;FNAME;AGE;COUNTRY;wself
[1] (NAME FNAME AGE COUNTRY)'Lescasse'
'Eric' '49' 'France'
[2] wself'ff'wi'Create'
'T_MyForm' 'Wait'
[3] R(wi'modalresult')NAME FNAME AGE
COUNTRY
A T_MyForm
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;io;wself
[1] © A T_MyForm B -- T_MyForm Template
Object
[2] © Use this template to create any new
class based on a TForm object
[3] © Replace T_MyForm by the new class
name everywhere in this function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ...
argumentN
[9] © (c)2000 Eric Lescasse[17sep00]
[10]
[11] io1
[12] :if
2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'T_MyForm"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[20] Zwi'.ed2.Create' 'TEdit'('wherelc' '>' '='Ð
100)('caption' 'First Name')
[21] Zwi'.ed4.Create' 'TEdit'('wherelc' '>' '='Ð
200)('caption' 'Country')
[22] Zwi'.ed5.Create' 'TEdit'('wherelc' '>' '='Ð
'=')('caption' 'Age')
[23] Zwi'.ed1.aplname' 'NAME'
[24] Zwi'.ed2.aplname' 'FNAME'
[25] Zwi'.ed4.aplname' 'COUNTRY'
[26] Zwi'.ed5.aplname' 'AGE'
[27] Zwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)
[28] Zwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>'
'=' Ð Ð)
[29]
[30] :case'Action'
[31] :selectwarg
[32] :case'class'
[33] wres'T_MyForm'
[34]
[35] :else
[36] wreswi'*'
[37] :end
[38] :else
[39] error'Unknown T_MyForm command: ',B
[40] :end
Note that
we have removed the bnRetry button from the T_MyForm object since
it was not useful.
Let’s call
the tt12 function:

Enter Baelen,
USA and ??? in the corresponding fields:

and press Enter. The tt12 function returns the
following data:
tt12
1 Baelen Eric ??? USA
]display tt12
.
--------------------------.
| .
-----..
---..
--..
--.|
| 1
|Baelen||Eric||???||USA||
| '------''----''---''---'|
'¹--------------------------'
If we
tested the result from the tt12 function for data types we would get the
following result:
dr¨tt12
11 82 82 82 82
This means
that all user input are returned as character strings.
We might
want to declare the Age field as being an integer field. This is done using the type property
with an integer or positiveinteger
value.
A T_MyForm
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;io;wself
[1] © A T_MyForm B -- T_MyForm Template
Object
[2] © Use this template to create any new
class based on a TForm object
[3] © Replace T_MyForm by the new class
name everywhere in this function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ...
argumentN
[9]
© (c)2000 Eric Lescasse[17sep00]
[10]
[11] io1
[12] :if
2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'T_MyForm"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[20] Zwi'.ed2.Create' 'TEdit'('wherelc' '>' '='Ð
100)('caption' 'First Name')
[21] Zwi'.ed4.Create' 'TEdit'('wherelc' '>' '='Ð
200)('caption' 'Country')
[22] Zwi'.ed5.Create' 'TEdit'('wherelc' '>' '='Ð
'=')('caption' 'Age')
[23] Zwi'.ed1.aplname' 'NAME'
[24] Zwi'.ed2.aplname' 'FNAME'
[25] Zwi'.ed4.aplname' 'COUNTRY'
[26] Zwi'.ed5.aplname' 'AGE'
[27] Zwi'.ed5.type' 'positiveinteger'
[28] Zwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>'
Ð Ð 0 112)
[29] Zwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>'
'=' Ð Ð)
[30]
[31] :case'Action'
[32] :selectwarg
[33] :case'class'
[34]
wres'T_MyForm'
[35]
[36] :else
[37] wreswi'*'
[38] :end
[39] :else
[40] error'Unknown T_MyForm command: ',B
[41] :end
If we now
run tt12 and check input collected by tt12 we get the following
result:
dr¨tt12
1 Lescasse
Eric 49 France
11 82 82 323 82
Now that we
have declared ff.ed5 (the Age field) as being of type integer
the value returned by the field is an integer value.
The 'type'
'positiveinteger'
property also have other advantages. It
prevents the user from typing other characters than tcbs,tcnl,'0123456789' in the field. When anothercharacter is typed by the user,
the character is automatically discarded and a beep sound is played.
Other
possible data types are:
It is not
enough to be able to collect data from the form but we also need to be able to
validate user input.
There are 2
kinds of possible validations:
APL validation
expressions are declared using the check property. All visual controls have a check
property.
The syntax
for field exit validation is:
'controlname'wi'check'
'APL_Validation_Expression' '"Error_Message"'
The APL_Validation_Expression
must be any APL expression which returns a Boolean scalar: 1 if
the validation fails and 0 otherwise.
APL_Validation_Expression may be an APL expression or an APL
function name as long as this function returns a Boolean value when it is run.
The APL_Validation_Expression
should use the APL variable name associated with the form field (or fields) as
in 'AGE>20'.
Note that
the Error Message must be enclosed in a double level of quotes. This allows to define Error Messages at
Design Time which are executed at Run Time.
Example:
'controlname'wi'check'
'APL_Expr' '"Please enter one of ',VAL'
where VAL
is a variable which only exists at Run Time, but not when the check
property is declared in the form constructor.
On the
other hand, the following expression:
'controlname'wi'check'
'APL_Expr' ('Please enter one of ',VAL)
would fail
at design time, the VAL variable existing only when the form is run, not
when it is constructed.
Example:
Let’s
change our T_MyForm object so that it does not accept ages below 20
or above 65.
A T_MyForm
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;io;wself
[1] © A T_MyForm B -- T_MyForm Template
Object
[2] © Use this template to create any new
class based on a TForm object
[3] © Replace T_MyForm by the new class
name everywhere in this function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ...
argumentN
[9]
© (c)2000 Eric Lescasse[17sep00]
[10]
[11] io1
[12] :if
2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'T_MyForm"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[20] Zwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð 100)('caption'
'First Name')
[21] Zwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð
200)('caption' 'Country')
[22] Zwi'.ed5.Create' 'TEdit'('wherelc' '>' '=' Ð
'=')('caption' 'Age')
[23] Zwi'.ed1.aplname' 'NAME'
[24] Zwi'.ed2.aplname' 'FNAME'
[25] Zwi'.ed4.aplname' 'COUNTRY'
[26] Zwi'.ed5.aplname' 'AGE'
[27] Zwi'.ed5.type' 'integer'
[28] Zwi'.ed5.check'
'(AGE<20)AGE>65' '"You must enter an age between 20 and
65!"'
[29] Zwi'.bnOk.Create'
'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)
[30] Zwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>'
'=' Ð Ð)
[31]
[32] :case'Action'
[33] :selectwarg
[34] :case'class'
[35]
wres'T_MyForm'
[36]
[37] :else
[38] wreswi'*'
[39] :end
[40] :else
[41] error'Unknown T_MyForm command: ',B
[42] :end
Let’s now
run the tt12 function and try to enter 75 in the Age
field. As you press Tab to leave
the Age field, you get the following error Message Box:

The Message
Box displayed is a Task Modal Message box. User must press Enter of click OK to exit this
Message Box.
Note that
the Message Box caption is the content of the system object apptitle
property as set in the Classes function. By default this apptitle property contains: APL+Win 3.6
Objects but you may of course
change it to reflect your application title.
When you
press Enter or click OK, the focus automatically returns to the Age
field and the previous value (49) is displayed again:

If you had
a whole series of checks to perform on the Age field, you could write
the APL_Validation_Expression as an APL function.
Example:
RT_MyForm_CheckAge
[1] RAGE<20
[2] RRAGE>65
wi'.ed5.check' 'T_MyForm_CheckAge' '"You must enter an
age between 20 and 65!"'
The syntax
for defining form wide validations is the following:
check 'APL_Val_Expr1' '"Error Message
1"' 'field1'
checkcheck,'APL_Val_Expr2'
'"Error Message 2"' 'field2'
...
checkcheck,'APL_Val_ExprN'
'"Error Message N"' 'fieldN'
formname wi'check'
check
Note that
the check property for form wide validations should be set at the TForm
object level. The form object must be a
TForm.
Thus you
may define several expressions and their associated error messages. There is also a third argument to each item
of the check property: the name
of the field where to return the focus when the error Message Box is closed.
APL
Validation Expressions may include several different form fields for form wide
validations.
Example:
Let’s
assume that we would like to check that the Age be between 25 and 60 for
someone living in France and between 30 and 55 for someone living in the USA,
while being between 20 and 65 for people in all other countries.
Here is how
we could write these checks:
A T_MyForm
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;check;io;wself
[1] © A T_MyForm B -- T_MyForm Template
Object
[2] © Use this template to create any new
class based on a TForm object
[3] © Replace T_MyForm by the new class
name everywhere in this function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ...
argumentN
[9]
© (c)2000 Eric Lescasse[17sep00]
[10]
[11] io1
[12] :if
2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'T_MyForm"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[20] Zwi'.ed2.Create' 'TEdit'('wherelc' '>' '='Ð
100)('caption' 'First Name')
[21] Zwi'.ed4.Create' 'TEdit'('wherelc' '>' '='Ð
200)('caption' 'Country')
[22] Zwi'.ed5.Create' 'TEdit'('wherelc' '>' '='Ð
'=')('caption' 'Age')
[23] Zwi'.ed1.aplname' 'NAME'
[24] Zwi'.ed2.aplname' 'FNAME'
[25] Zwi'.ed4.aplname' 'COUNTRY'
[26] Zwi'.ed5.aplname' 'AGE'
[27] Zwi'.ed5.type' 'integer'
[28] Zwi'.ed5.check' '(AGE<20)AGE>65'
'"You
must enter an age between 20 and 65!"'
[29] Zwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)
[30] Zwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>'
'=' Ð Ð)
[31] check '(COUNTRY"USA")^(AGE<30)AGE>55'
'"Age must be between 30 and 55 for
Americans!"'(A,'.ed5')
[32] checkcheck,'(COUNTRY"France")^(AGE<25)AGE>60'
'"Age must be between 25 and 60 for French!"'(A,'.ed5')
[33] Zwi'check'check
[34]
[35] :case'Action'
[36] :selectwarg
[37] :case'class'
[38]
wres'T_MyForm'
[39]
[40] :else
[41] wreswi'*'
[42] :end
[43] :else
[44] error'Unknown T_MyForm command: ',B
[45] :end
tt12

If you want
to force the user to enter data in a control, you can use the control must
property.
Its syntax
is:
'controname' wi
'must' missingvalue
where controlname
is the name of the control which must not stay empty and missingvalue is
the value such that the control is considered empty when it contains it.
Example:
A T_MyForm
B;C;D;E;F;G;H;I;J;K;L;M;N;O;P;Q;R;S;T;U;V;W;X;Y;Z;check;io;wself
[1] © A T_MyForm B -- T_MyForm Template
Object
[2] © Use this template to create any new
class based on a TForm object
[3] © Replace T_MyForm by the new class
name everywhere in this function
[4] © A
object name
[5] © B
'property'
[6] © or 'property'value
[7] © or 'Method'
[8] © or 'Method'argument1 ...
argumentN
[9]
© (c)2000 Eric Lescasse[17sep00]
[10]
[11] io1
[12] :if
2¬nc'A' ª Awself ª :end
[13] :select B
[14] :case'New'
[15] wselfA wi'*Create' 'TForm'
[16] C'T_MyForm"Action"'
[17] CC,tcnl,wi'*onAction' © inherit from TForm
[18] wi'*onAction'C
[19] Zwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð
200)('caption' 'Name')
[20] Zwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð
100)('caption' 'First Name')
[21] Zwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð
200)('caption' 'Country')
[22] Zwi'.ed5.Create' 'TEdit'('wherelc' '>' '=' Ð
'=')('caption' 'Age')
[23] Zwi'.ed1.aplname' 'NAME'
[24] Zwi'.ed2.aplname' 'FNAME'
[25] Zwi'.ed4.aplname' 'COUNTRY'
[26] Zwi'.ed5.aplname' 'AGE'
[27] Zwi'.ed5.type' 'integer'
[28] Zwi'.ed5.check' '(AGE<20)AGE>65'
'"You must enter an age between 20 and 65!"'
[29] Zwi'.ed1.must' ''
[30] Zwi'.bnOk.Create'
'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)
[31] Zwi'.bnCancel.Create'
'TCancelButton'('wherelc' '>' '=' Ð Ð)
[32] check '(COUNTRY"USA")^(AGE<30)AGE>55'
'"Age must be between 30 and 55 for
Americans!"' (A,'.ed5')
[33] checkcheck,'(COUNTRY"France")^(AGE<25)AGE>60'
'"Age must be between 25 and 60 for
French!"' (A,'.ed5')
[34] Zwi'check'check
[35]
[36] :case'Action'
[37] :selectwarg
[38] :case'class'
[39]
wres'T_MyForm'
[40]
[41] :else
[42] wreswi'*'
[43] :end
[44] :else
[45] error'Unknown T_MyForm command: ',B
[46] :end
Run
function tt12 and erase the content of the Name field when the
form gets displayed, then hit Enter or click the OK button.
The
following error Message Box is displayed:

Note that
the culprit field is flashing, being alternatively painted in red and in white.
When you
hit Enter or click the Message Box OK button, the focus returns
to the Name Edit field.
For some
reason you may decide that a field is considered empty when it contains a given
value which is not necessarily the empty vector. For example assume we want to initialise the Name field
with the following string: (enter
your Last Name here) and still want the form to refuse closing until the
user has entered his Last Name in this control.
We could
simply have defined the must property for the ff.ed1 (the Name
field) as follows on line 29 of T_MyForm:
Zwi'.ed1.must'
'(enter your Last Name here)'
And changed
the tt12 function as follows:
Rtt12;NAME;FNAME;AGE;COUNTRY;wself
[1] (NAME
FNAME AGE COUNTRY)'(enter your Last Name here)' 'Eric' 49 'France'
[2] wself'ff'wi'Create' 'T_MyForm' 'Wait'
[3] R(wi'modalresult')NAME FNAME AGE COUNTRY
Let’s run
the tt12 function and immediately click Enter to try to close the
form:

and the
form will refuse to close itself until the user has entered his name in the Name
field.
Now that we
have described how one can quickly design “perfect forms” with minimum efforts
using APL+Win 3.6 Objects, let’s explore other objects in the product.
First, all
APL+Win existing objects (except the System object) have a counterpart in
APL+Win 3.6 Objects which has the same name with a T prefix.
For
example, there is a DateTime object in APL+Win and there is a TDateTime
object in APL+Win 3.6 Objects.
Similarly,
there is a CommandBar object in APL+Win and there is a TCommandBar
object in APL+Win 3.6 Objects.
All APL+Win
3..6 Objects which have an APL+Win counterpart object which understands the where
property, also understand the following properties:
Here is the
complete list of APL+Win 3.6 Objects:
TADO TDoc TImagelist TProgressDlg
TAPLEdit TDualSelect TInfo TQuestion
TAboutBox TDundasGrid TInstall
TRichEdit
TAgent TEdit TInternet TScroll
TButton TEditList TLabel TSelector
TCancelButton TEditMenu TList TSpinner
TCheck TEditSelect TSplitter
TChildForm TEditSpin TListview TSpread
TEmail TMDIForm TStatus
TChooseColor TExcel TMaskEdit TStopWatch
TChooseFont TFOne TMedia TTextFile
TClipBoard TFTP TMenu TTimer
TClock TFileMenu TMsgBox TTip
TCombo TFileMenuDef TNavigator TToolBar
TComboDrive TFlatButton TNetwork TToolbox
TComboFilter TFlexGrid TOKButton TToolsMenu
TComboList TForm TObject TTrackbar
TCommandBar TFormEditor TOpenFile TTree
TCommandButton TFormOne TOption TVLine
TCueCard TFrame TOutlook2 TViewMenu
TCwinForm TGoMenu TPFKeys TWebBrowser
TDHTML TGraphX TPage
TWebServer
TDateTime TGrid TPassword TWinMenu
TDateTimeFr THLine TPicture TYesNo
TDates THTML TPopupMenu TModalCall
TDebug THelp TPrinter
TWord
TDisplay THelpMenu TProgress
I have
highlighted objects which have a counterpart standard object in APL+Win.
Here are
the available Collections:
|
Collection |
Description |
|
The
parent of all Objects |
TObject:
The parent of all other objects: include many useful properties and
methods, therefore available from all other objects |
|
The Common
Dialog Box Collection |
Objects
allowing to use common Windows dialog boxes |
|
The Complex
Windows Collection |
Various
complex Window objects using several or many other objects |
|
The Graphics
Collection |
Objects
for drawing graphics |
|
The Grids
Collection |
Grid
objects generally based on external ActiveX components |
|
The Help
Collection |
Various objects
for displaying different kind of help |
|
The Interactive
Collection |
Objects
requesting input from the user through Windows |
|
The Interface
Collection |
Various
objects for improving or simplifying the development of a Windows application |
|
The Internet
Collection |
Objects
for using Internet from an APL+Win application including sending Emails,
files through FTP, browsing Web pages, etc. |
|
The Menu
Collection |
Objects
for inserting full standard menus like a File menu, en Edit menu, a Windows
menu or a Help menu in a Windows application |
|
The Microsoft
Collection |
Objects
for using Excel and Word directly from an APL+Win application |
|
The Miscellaneous
Collection |
Various
objects for using the Clipboard, Text Files, Dates, Programmed Function Keys,
etc. |
|
The ODBC
Collection |
Objects
for accessing and working with Relational Databases |
|
Object |
Description |
TObject |
The
parent of all other objects: include many useful properties and methods,
therefore available from all other objects |
|
Object |
Description |
TChooseColor |
An object
version of the Choose Color Windows standard dialog |
TChooseFont |
An object
version of the Choose Font Windows standard dialog |
TOpenFile |
An object
version of the Open File Windows standard dialog |
|
Object |
Description |
TAPLEdit |
An object
for calling the APL editor under program control |
TChildForm |
A Child
Form class for use within the TMDIForm object when designing MDI applications |
TFormEditor |
A Visual
APL+Win Form Editor object |
TMDIForm |
An MDI
Form object complete with its standard, menus, status bar, clock, etc...
Includes engine for creation of multiple child forms, automatic updates of
Windows menu, etc. |
TOutlook2 |
An object
with a complete Microsoft Outlook-like interface which you can use as the
chore of any new APL+Win application with an Outlook interface |
|
Object |
Description |
TGraphX |
A 2D and
3D graphics object based on APL2000 GraphX product. Requires to own a copy of
GraphX |
|
Object |
Description |
TDundasGrid |
A grid
object based on the Dundas Grid component |
TFOne |
A Formula
One Grid Object, allowing you to include input grids, display tabular data,
easily make Excel-quality print outs from your APL applications. Requires
Formula One v5 or V6. |
TFormOne |
A TForm
object with a TFOne (Formula One) object using the whole client area of the
form. |
TFlexGrid |
A
VideoSoft Flex Grid Object useful to write user interfaces to databases.
Requires Videosoft FlexGrid v6 or v7. |
TGrid |
An object
simplifying the use of the APL+Win Grid object |
TSpread |
A
spreadsheet object based on the Farpoint Spread control |
|
Object |
Description |
TCueCard |
Single
page (or dual pages) nice looking help panels |
THelp |
A class
allowing to display a Windows .HLP help file, or any topic from this help
file, directly. |
TInfo |
A small
nice looking floating window class replacing forms status bar to inform users
about tasks progress |
TTip |
A special
window object designed to display the Tip of the Day. Contains buttons to
navigate among available tips. Requires: LIGHT.BMP. |
|
Object |
Description |
TMsgBox |
A Message
Box Object |
TProgressDlg |
A
complete Window dialog with a TProgress object within it |
TPassword |
A dialog
object allowing to enter a password |
TQuestion |
An object
displaying a dialog with a question and requesting/returning user input |
TYesNo |
A special
king of a TMsgBox object handling Yes/No questions |
The
Interface Collection contains objects which make it easier to design complex
GUI interfaces.
|
Object |
Description |
TAboutBox |
An About
Box dialog box object for the Help menu of your applications |
TAgent |
A class
allowing you to include and use Microsoft Agent 2.0 characters within your
APL applications |
TCancelButton |
A special
kind of a TButton which knows how to cancel a form |
TComboDrive |
A special
kind of a TCombo object displaying available drives |
TComboFilter |
A special
kind of a TCombo object which automatically displays its list of items when
getting focus and reduces it as user types characters in its Edit field, to
those itmes which match these characters |
TComboList |
A
multi-column combo box with automatic list selection when typing in the Edit
field |
TDisplay |
A NotePad
like form object used to present results and data to the user in a nice
looking form |
TDualSelect |
An object
combining 2 List Boxes and 4 Buttons in a Frame. Buttons allow to transfer
items from one list box to the other. |
TEditList |
A
combination of a TEdit and of a TListView to allow easier selection from a
single or multiple columns list. Inherits TEdit. |
TEditSelect |
|
TEditSpin |
A
combination of a TEdit and of a TSpinner objects. Allows to enter data in the
edit field by clicking the TSpinner object buttons |
TFlatbutton |
A special
type of buttons similar to MS Word 97/2000 flat toolbar buttons which pop up
when mouse hovers them |
THLine |
An
horizontal separation line object to enhance your form visual quality |
TMaskEdit |
|
TOKButton |
A special
kind of a TButton which knows how to closel a form with the Enter key, etc. |
TSplitter |
A
Splitter object allowing you to resize various parts of a form with your
mouse. |
TVLine |
An
vertical separation line object to enhance your form visual quality |
|
Object |
Description |
TDHTML |
An HTML
editor object with methods and properties allowing you to develop and include
a complete WYSIWYG HTML editor in your APL applications |
TEmail |
An object
allowing to send E-mails from an APL+Win application, optionally including
file attachments |
TFTP |
An object
alowing you to send and receive files over the Internet |
THTML |
A non
visual object allowing you to generate HTML pages easily from APL. Contains
methods to convert nested arrays to HTML, add titles, rules, paragraphs of
text, images, etc. |
TInternet |
|
TWebBrowser |
An
Internet Explorer object complete (except its menus) which you can embed
within your APL+Win forms to develop Internet aware applications |
TWebServer |
An
Internet Web Server object allowing you to serve HTML pages and use APL+Win
as a server application in an Internet environment |
|
Object |
Description |
TEditMenu |
A
complete Edit Menu Object for your forms, with accelerators, etc. |
TFileMenu |
A File
Menu object for your forms, pre-build options, with accelerators, etc |
TFileMenuDef |
A
complete default File Menu object. Inherits TFileMenu. |
TPopupMenu |
A Popup
menu object, usually displayed when user right clicks his mouse |
TToolsMenu |
A Tools
menu object for the TOutlook object |
TViewMenu |
A
complete View Menu Object for your forms, with accelerators, etc |
TWinMenu |
A
complete Window Menu Object for your forms, with accelerators, etc |
|
Object |
Description |
TExcel |
A COM
Object allowing you to load and use Excel as wished from your APL
applications. You may create workbooks and worksheets, populate sheet ranges,
read/write APL data from/to Excel, save spreadsheets, format data, print it,
change Excel dialog settings, etc... all programmatically from APL+Win |
|
Object |
Description |
TAPLEdit |
|
TClipBoard |
An object
to copy data to the Windows ClipBoard or retrieve data from it |
TClock |
A Digital
clock inheriting the TLabel object |
TDates |
A non
visual class allowing all kinds of date calculations and manipulations (year
2000 compatible of course!) |
TDebug |
|
TDoc |
|
TInstall |
|
TNetwork |
A non
visual object to connect/disconnect network drives, get various information
about the network, network user name, etc. |
TPFKeys |
|
TStopWatch |
A Stop
Watch non visual object |
TTextFile |
|
|
|
|
The ODBC
Collection contains object which allows you to directly work with Relational
Databases. These include:
|
Object |
Description |
TADO |
A non
visual object to work with Relational Databases through ActiveX Data Objects |
TNavigator |
A buttons
bar object to navigate through database records |
TODBC |
A non
visual object to work with ODBC databases |
APL+Win
3.5+ lets you define inheritance when you create your own objects.
Thus you
can create objects which inherit from other objects which themselves can
inherit from other objects.
When an
object inherits from another object, it may use any of the other object
properties or methods unless the object has its own property for method of the
same name.
To declare
that an object TObj1 inherits from two other objects called TObj2
and TObj3, you define the onAction event handler for TObj1
as follows:
C'TObj1"Action"'
CC,tcnl,'TObj2"Action"' ©
inherit from TObj2
CC,tcnl,'TObj3"Action"' ©
inherit from TObj3
wi'*onAction'C
(assuming
that an instance of TObj1 has been created and is the current object).
All APL+Win
3.6 Object inherit from a root object called TObject. When you load the APL+Win 3.6 OBJECTS.W3
workspace or run the Classes function, an instance of TObject
called oo is created.
TObject has a large number of properties
and methods:
70 TELPRINT 'oo'wi'Properties'
apldir caption enabled must
sysmenu
aplhelp check
handlers noresize tooltip
aplhelpfile clipsiblings inifile ontop
where
aplname connected installdir resources wherelc
apptitle countries just spy windowsdir
attach country moveable suffix
70 TELPRINT 'oo'wi'Methods'
A2R DecimalSeparator Objects
ShowDemo
APLHelp DemoShow P_Default ShowEvent
AddLF DemoShow P_DevMode ShowTaskBar
Ansi2Av Doc
P_DlgError SmgrHandles
Av2Ansi DocClass P_W_Read SsColumns
Bitmaps EnumChildWindows P_W_Write
TextSize
C2I EnumFonts Packws UpdateControls
C2W FileExist PaintDesktop UsedClasses
Center Files Properties UsedClassesByObj
CenterOn FullName Protect VT
ChStyle GetBitmapSize R2A VT_Dispatch
Check GetCommandLine Redim
VT_Variant
CheckClose GetWorkArea RegisterServer VV
Children HideTaskBar RemoveComments W2C
Classes I2C
RemoveQuotes W_CreateFilter
ClipSiblings Lastfns SendKeys Wait
ComputeRange ListSeparator SessionFocus WebBrowserClass
CountryIndex Methods SetAplNames XClass
D2C NonUsedClasses ShellExecute XClassLicense
DHTMLClass Nread Show Xlicense
Any APL+Win
3.6 Object that you create, may use any of these properties and methods
additionally to its own properties and methods.
Example:
'ff'wi'Create' 'TForm'
ff
'ff'wi'GetCommandLine'
"C:\APLWIN36\aplw.exe" 24m c:\winnt\aplw.ini
'ff'wi'country'
1
'ff.ed'wi'Create' 'TEdit'
ff.ed
'ff.ed'wi'windowsdir'
C:\WINNT\
'ff.ed'wi'FileExist' 'c:\aplwin36\aplw.exe'
1
When
developing Windows applications there are a number of basic interactive
functions which everyone needs and which must be as easy to use as possible.
The Ok
function displays a simple task modal message box with an OK button.
Its right
argument is the message to be displayed.
The message box title is whatever is currently recorded in the TObject
apptitle property.
The Ok
function makes use of the TMsgBox object.
It creates an instance of the TMsgBox object called fmMsgBox (if
it does not yet exist, otherwise simply use the existing fmMsgBox
window) to display the message.
The code of
the Ok function is:
RA Ok
M;wself
[1] © A Ok M - Display message box with message M
[2] © A
icon type ('s'(stop), 'i'(info), '?'(query)
or '!'(exclamation))
[3] © M
message string
[4] © Requires: (F) TMsgBox
[5] © (c)2000 Eric Lescasse
[6]
[7] :if
0=nc'A' ª A'i' ª :end
[8] :if
0=½'fmMsgBox'wi'*self'
[9] wself'fmMsgBox'wi'*Create'
'TMsgBox'('text'M)('buttons' 'OK')
('icon'A)('mode' 'T')
[10] wi'title'(wi'apptitle')
[11] :else
[12] 'fmMsgBox'wi'Set'('text'M)('buttons' 'OK')('icon'A)
[13] :end
[14] R'fmMsgBox'wi'Show'
Example:
Ok'Enter a positive
number!'
Note that
the function returns 1 when you click the OK button.

If you need
to enter a long message, you may simply make it multi-line by inserting new
line characters (TCNL) at the appropriate place.
Example:
msg'Enter a positive
number!'
msgmsg,tcnl,tcnl,'You
may use digits, the minus sign and'
msgmsg,tcnl,'the
letter E as in 10234.65E¯3'
Ok msg

You may use
a different icon by using a left argument.
Possible left argument values are:
Example :
'!'Ok msg

or
's'Ok msg

The OkCancel
function is similar to the Ok function except that it displays a Message
Box with 2 buttons: an OK button
and a Cancel button.
The
function returns 1 if the OK button was pressed, 2 if the Cancel
button was pressed.
The OkCancel
function window is called fmMsgBox
Example:
'?'OkCancel'Continue with installation?'

Although
you may sometimes use the OkCancel function to ask a question, this task
is more often performed by the YesNo function.
The YesNo
function is similar to the OKCancel function except the 2 displayed
buttons are Yes and No.
Also, you
may not set the icon which is always a Question Mark.
The YesNo
function window is called fmYesNo.
Example:
YesNo'Do you want to
exit?'

The YesNoCancel
function is very similar to the YesNo function. It just has an additional Cancel
button.
The YesNoCancel
function returns 1 if Yes was clicked, 2 if No was
clicked or 3 if Cancel was clicked.
The YesNoCancel
function window is called fmYesNo.
Example:
msg'Do you want to
save changes?'
msgmsg,tcnl,tcnl,'(Press
Cancel to go on with this form)'
YesNoCancel msg

Note that a
clean way of using the YesNoCancel in your code is such constructs as:
:select YesNoCancel msg
:case 1 © Yes
...
:case 2 © No
...
:case 3 ©
Cancel
...
:end
The Question
function asks a simple question on the screen and returns a 2-item nested
vector:
Example:
½Question'Enter
your Name'
1 Lescasse
2

Note that
this form is resizable:

If you want
to provide a default value you may do so through the Question left argument:
'Eric'Question'Enter your
Name'

You may
specify additional properties for the TQuestion Edit control in
the Question right argument.
Example:
45 Question'Age'('type'
'positiveinteger')('check' 'ANSWER<49' '"Too young!"')

Having
specified a type of positiveinteger, user may only type digits in the
input field.
The form
name used by the Question function is:
fmQst
As for the Ok, OkCancel and other functions described above
the fmQst is automatically created if it does
not exist, but is not recreated if it already exists.
The first
item of the Question function result is:
The second
item of the Question function result is the user answer.
You may use
the Question function as follows:
:selectresQuestion'Enter
your Name'
:case 1
© user pressed Enter of
clicked OK
...
:case 2
© user pressed Esc or
clicked Cancel
...
:end
The Password
function is very similar to the Question function. The only difference is that * characters are
displayed in the Edit control as the user types his password.
'john'Password'Enter your
password'

The
function returns the same kind of result as the TQuestion function
returns.
If the user
enters the right password, the function returns a 3-item vector containing 1,
the password and an empty vector.
If the user
fails to enter the right password, an error message is automatically displayed.

User may
try 3 times : after the third trial, if the password is still wrong, the Password
function returns 2 as its first result item.
If you want
to allow the user to be able to change his password, you must set the change
property to 1.
Example:
'john'Password'Enter your
password'('change'1)
1 john eric

When the change
property is set to 1, a Change button is displayed.
If the user
clicks the Change button without having first entered his current
password, the following error message is displayed:

Otherwise,
the form extends allowing to enter a new password twice.

If the user
fails to enter the same new password twice an error message is displayed.

and finally
the Password function returns 1, the old password and the new
password when the user clicks the OK button.
aaa'john'Password'Enter
your password'('change'1)
]display aaa
.
--------------.
| .
---..
---.|
| 1 |john||eric||
| '----''----'|
'¹--------------'
The TPassword
object is a good example of an APL+Win 3.6 Objects which uses other objects as
well as APL+Win 3.6 Objects interactive functions.
The Info
function uses another object called TInfo which is used to display important
information in a very visible manner to the user.
The Info
function is generally used as follows:
Info'This is an important message'
![]()
The message
is centered on the screen and stays displayed until you run:
Info''
You may
call additional TInfo methods, passing them as additional arguments to the Info
utility. This way, you may for example
center the TInfo message on top of a given form:
'ff'wi'Create' 'TForm' '*Show'
Info'This is an important message'('WaitOn' 'ff')('CenterOn' 'ff')

You may
also use the Info function to display a warning message for a given duration:
2 Info'This is an important message'
The message
will display for 2 seconds and then disappear.
You may
also change the message background color as follows:
2 Info'This is an important message'('color'255)
The Info
utility and the TInfo object are very useful to attract the user attention much
more than Status Bar messages. They
also are very colourful and nice looking small Windows which gives more life to
your application.
With TExcel
you may fully use and pilot Excel from APL+Win.
This allows
you to:
Let’s see
how we may use this object.
Let’s
create an instance of this object:
'ee'wi'Create'
'TExcel'
Here are
the available object properties and methods:
'ee'wi'Properties'
bookname ontop sheetname
60 TELPRINT 'ee'wi'Methods'
AddBook FontName PrintGridLines
AddChartObject FontSize Quit
AddPageBreak FooterMargin Range
BackColor Format RightFooter
Border Formula RightHeader
BottomMargin Get RightMargin
CenterFooter GetFormula RowHeight
CenterHeader GridLines Save
CenterHorizontally HAlign SaveAs
CenterVertically HeaderMargin Set
ColumnWidth Import SetFormula
DefaultFilePath Interactive
Sheet
Empty LeftFooter Show
Export LeftHeader TopMargin
FitToPagesTall LeftMargin Used
FitToPagesWide Load VAlign
FontBold Name Value
FontColor Orientation Dialog
FontItalic Print
Once you
have created an instance of the TExcel object, you first need to
initialise it, by generally
adding a
WorkBook to it, making it visible and, if you want to most easily work with it
from the APL session, make it on top.
'ee'wi'AddBook'1 ©
create a workbook with 1 worksheet
'ee'wi'Sheet'1 © activate sheet 1
'ee'wi'visible'1
'ee'wi'ontop'1

Note that
the TExcel Show method does all of the above instructions, so the
fastest way to create a TExcel object and to display it is:
'ee'wi'Create'
'TExcel' 'Show'
Adding APL data to the Excel sheet is as easy as defining a range with the Range
method and invoking the Value method.
Example:
'ee'wi'Range'
'B2:G8'
'ee'wi'Value' (7
6½36840+¼42)

Numeric
values are automatically converted to Excel numeric data types.
However you
may want to convert some values yourself using the VT utility before
passing them to the Value method.
Example:
'ee'wi'Value' (7
VT¨7 6½36840+¼42)

The 7 VT
conversion tells Excel to accept the values as Dates.
Here are
the possible left arguments for APL data conversion to Excel (which you can
obtain by issuing: 'oo'wi'?VT' )
TypeNames ScalarTypes
ArrayTypes
=================================
Empty 0
Null 1
Short 2
8194
Long 3 8195
Float 4
8196
Double 5 8197
Currency 6 8198
Date 7 8199
String 8 8200
Object 9 8201
Error 10 8202
Boolean 11 8203
Variant 12 8204
DataObject 13
8205
Byte
17 8209
Another simpler
way to add APL values to the Excel sheet is to use the Add method.
With this
method you pass 2 arguments:
Example:
First let’s
empty the Excel cells previously filled with our array:
'ee'wi'Value' (0
VT¨7 6½0)
(0 VT 0 represents an empty Excel cell).
Now let’s
define a little APL nested matrix:
report'Jan' 'Feb'
'Mar' 'Apr' 'May' 'Jun'®?3 6½100000
report'' 'APL+Dos'
'APL+Win' 'APL+Unix',report
report
Jan Feb
Mar Apr May Jun
APL+Dos 31925 62927 12672
65126 62164 80308
APL+Win 24785 47644 38932
20326 2838 90168
APL+Unix 42650 14203 94749 41032 13119 88565
and install
it within the Excel sheet starting at cell B2:
'ee'wi'Add' 'B2'
report
B6 I2

Note that
the Add method returns 2 cell coordinates.
The first
one is the cell from which you may want to add more data below the table you
just added to Excel: the second one is the cell from which you may want to add
more data to the right of the table just added to Excel.
As with the
Value method you may want to convert some or all of your matrix cells to
Excel data types before passing your matrix to the Add method, using the
VT utility.
You may add
a border around the table. Remember
that the Range you have set when adding the matrix remains active until
you explicitly change it with the Range method or add new data with the Add
or Value methods.
'ee'wi'Border'1 3
'ee'wi'Range'
'B2:B5;B2:H2'
'ee'wi'Border'1 3
Note that
the list separator (here ; may be different in other countries: for
example, in the United States you must specify the range list as: 'B2:B5,B2:H2')

You may
align text in cells as wished using the HAlign method:
'ee'wi'Range'
'C2:H2'
'ee'wi'HAlign'
'right'
If you need
information on how to use a method, remember you may use the question mark:
'ee'wi'?HAlign'
Get or Set horizontal
alignment for the selected range
Syntax: 'obj'wi'HAlign' halign
halign: 'right' 'left' 'justify' 'center' 'general'
'fill' or 'centeracross'
You may
change background cell colors using the BackColor property:
'ee'wi'Range'
'B3:B5;C2:H2'
'ee'wi'BackColor'(192
192 192)
You may
change the fonts and font attributes using the FontName, FontSize,
FontBold, FontItalic and FontColor methods:
'ee'wi'Range'
'C3:H5'
'ee'wi'FontName'
'Impact'
'ee'wi'FontSize' 16
'ee'wi'FontColor'
255

You may use
the ColumnWidth method to specify one or more columns width in points
for a range of cells.
Example:
'ee'wi'ColumnWidth'20
The TExcel
object would be useful even if it only provided access from APL+Win to the
extraordinary Excel print engine.
You may
indeed use TExcel to populate a worksheet with APL data, use some or all
of the formatting methods we have seen above and submit the worksheet to the
printer.
To print
the entire worksheet:
'ee'wi'Print'
You may
pass parameters to the Print method to customize your print job. Here are the possible parameters:
parameters[1]
„… from page number
parameters[2]
„… to page number
parameters[3]
„… # of copies
parameters[4]
„… print preview
parameters[5]
„… active printer
parameters[6]
„… print to file
parameters[7]
„… collate
parameters[8]
„… print to file name
For
example, if we wanted to install all APL function names and their sizes in the
Excel sheet and then to do a Print Preview of the second page only, here
is what we would do:
'ee'wi'Empty' © to empty the worksheet
'ee'wi'Add'
'A1'((split nl 3),[1.5]size nl 3)
'ee'wi'Print'2 2 1 1

Before
printing you may however want to set margins, define headers and footers, etc.
Simply use
one of the following methods: LeftMargin,
RightMargin, TopMargin et BottomMargin to set the various
margins in centimeters.
Example:
'ee'wi'LeftMargin'1
'ee'wi'RightMargin'1
You may set
headers using the following methods: LeftHeader,
CenterHeader, RightHeader, LeftFooter, CenterFooter
and RightFooter.
You may use
control characters to specify various formatting and output within your headers
and footers. Here are these control characters:
&E Left
align next chars
&C Center
next chars
&D Right
align next chars
&L Activate
or disactivate double underline printing
&X Activate
or disactivate exponants printing
&Y Activate
or disactivate indices printing
&G Activate
or disactivate bold printing
&I Activate
or disactivate italic printing
&S Activate
or disactivate underline printing
&B Activate
or disactivate barré
&J Prints current date
&H Prints
current hour
&N Prints
document name
&A Prints
the workbook name
&P Prints
the page number
&P+nombre Prints
the page number+N
&P-nombre Prints
the page number-N
&& Prints
the & character
&"nom_police"
Prints the next chars with the specified font (within double quotes)
&nn Prints
the next chars with font size nn (2 digits in points)
&T Prints
the total number of pages in the document
Example:
'ee'wi'LeftFooter'
'&08 &"Verdana" &N &J &H Page &P/&T'
You may
call the CenterHorizontally and/or CenterVertically methods to
horizontally or vertically center the pages to print.
Example:
'ee'wi'CenterHorizontally'1
It is also
possible to call all Excel dialog boxes from APL, so that you may let the user
select various settings himself.
You call an
Excel dialog box by invoking the Dialog method with the dialog number as
an argument.
Example:
'ee'wi'Dialog'8

Other
example:
'ee'wi'Dialog'84

It is
possible to pass arguments to the dialog box to initialise some dialog box
controls.
Example:
'ee'wi'Dialog'8 2 1
4
This calls
the Print dialog and presets the Page(s) option button and
installs 1 in the From page edit control and 4 in the To
page edit control:

As an
example here are the possible parameters for the Excel Print dialog:
range_num,
from,
to,
copies,
draft,
preview,
print_what,
color,
feed,
quality,
y_resolution,
selection,
printer_text,
print_to_file,
collate
APL+Win 3.5
has introduced an extremely important new feature which may change the way with
which we organize and develop APL applications: the ability to create our own
objects.
This allows
us to:
-
do
Object Oriented Programming
-
program
whole applications exclusively using Objects
-
reuse
APL code very easily
-
standardize
the way we develop applications
It is
possible to create Objects so that an Object be a self-contained APL function
where each Object property and method is a simple :select structure :case
section in this function.
User
defined APL+Win Objects need not be Visual objects. You may create non visual objects like an object to connect and
work with Relational Databases (like TADO in APL+Win 3.6 Objects) and TDates
to make various computations involving dates.
This paper
just touched a few of the Objects contained in APL+Win 3.6 Objects and showed
through examples how to use these objects to build “perfect forms” without the
need of a Form Editor, using a few simple properties (wherelc, attach,
…)
It also
showed the structure of a User Defined APL+Win Object (TFormClass), as
used throughout “APL+Win 3.6 Objects”.
It then
showed a few Interactive functions (Ok, OkCancel, YesNo,
…) and part of one more complex object TExcel which may in particular be
used to solve almost any printing requirements in any APL+Win application.
You may
find a more lengthy version of this document with more examples showing a lot
of other APL+Win 3.6 Objects on the following Web Site: