Rapid Development with APL+Win 3.6 Objects

by Eric Lescasse

eric@lescasse.com

http://www.lescasse.com

 

Introduction

 

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

 

Basic Principles


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'




Designing Forms

 

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'

 




Designing your form

 

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.

 

The margins property

 

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.

 

The gaps property

 

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.

 

Visual controls

 

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.

 


Visual controls 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)

 

The Reference Control

 

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. 

 

The margins and gaps properties

 

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 TEdit caption property

 

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.

 

 

The TForm escape property

 

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.

The wherelc 5th 6th 7th and 8th arguments

 

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'

 

 

 

The TForm Redim method

 

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.

 

 

The TForm Show and Wait methods

 

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.

 

Right justifying controls on a form

 

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'

 

 

 

Using all the remaining space on a form

 

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?

 

Keeping some wherelc elements unchanged

 

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.

 

The attach property

 

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'

 

 

Centering controls in a form

 

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'        

 

 

limitwhere for Redim

 

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.

 

Other wherelc features

Extending an object up to another object on the form

 

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:

 

 

Limiting control input size

 

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.

 

 

Auto-documenting your forms

 

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!

 

 


Maintaining forms

 

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.

 

Using relative naming notations when developing forms

 

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]       Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[3]       Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð 100)('caption' 'First Name')

[4]       Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')

[5]       Z„Œwi'.ed3.Create' 'TEdit'('wherelc' '>' '=' Ð '=')('caption' 'Age')

[6]       Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc' '=ff.ed1' '>' Ð Ð 0 112)

[7]       Z„Œwi'.bnRetry.Create' 'TButton'('wherelc' '>' '=' Ð Ð)('*caption' 'Retry')

[8]       Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[9]       Z„Œwi'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.

 


Developing forms as new user defined objects

 

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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'TFormClass"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]  :case'Action'

[20]      :select†Œwarg

[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]          Œwres„Œwres,Œtcnl,"Syntax:  'object'Œwi'property'{value}"

[37]          Œwres„Œwres,Œtcnl,"value: value description"

[38]          Œwres„Œwres,Œtcnl,"Example: 'object'Œwi'property'..."

[39]      :case'property'

[40]          :if 1=½Œwarg

[41]              Œwres„Œwi'*‘‘property'

[42]          :else

[43]              C„2œŒwarg

[44]              Œwi'*‘‘property'C

[45]          :end

[46]      ©-------------------------------------------© sample method

[47]      :case'?Method'

[48]          Œwres„'Description'

[49]          Œwres„Œwres,Œtcnl,"Syntax:  'object'Œwi'Method'{param1}{param2}..."

[50]          Œwres„Œwres,Œtcnl,"param1:  parameter 1 description"

[51]          Œwres„Œwres,Œtcnl,"param2:  parameter 2 description"

[52]          Œwres„Œwres,Œtcnl,"Example: 'object'Œwi'Method'..."

[53]      :case'Method'

[54]

[55]      :else

[56]          Œwres„Œwi'*'

[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:

 

  1. press Ctrl+R and replace TFormClass by your form class name, say T_MyForm (click Replace All to be sure to replace all occurrences of TFormClass by T_MyForm)

  2. Then, add lines of code to the :case'New' section of your T_MyForm object to create all the controls needed in your form (note: you may simply copy/paste lines from a sample function like the tt function shown above)

  3. Append T_MyForm to the list of User Defined classes declared in the Classes function

  4. Run the Classes function to declare your new T_MyForm class to the APL+Win system

 

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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'T_MyForm"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]          Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[20]          Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð 100)('caption' 'First Name')

[21]          Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')

[22]          Z„Œwi'.ed5.Create' 'TEdit'('wherelc' '>' '=' Ð '=')('caption' 'Age')

[23]          Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)

[24]          Z„Œwi'.bnRetry.Create' 'TButton'('wherelc' '>' '=' Ð Ð)('*caption' 'Retry')

[25]          Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[26]

[27]  :case'Action'

[28]      :select†Œwarg

[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]          Œwres„Œwres,Œtcnl,"Syntax:  'object'Œwi'property'{value}"

[45]          Œwres„Œwres,Œtcnl,"value: value description"

[46]          Œwres„Œwres,Œtcnl,"Example: 'object'Œwi'property'..."

[47]      :case'property'

[48]          :if 1=½Œwarg

[49]              Œwres„Œwi'*‘‘property'

[50]          :else

[51]              C„2œŒwarg

[52]              Œwi'*‘‘property'C

[53]          :end

[54]      ©-------------------------------------------© sample method

[55]      :case'?Method'

[56]          Œwres„'Description'

[57]          Œwres„Œwres,Œtcnl,"Syntax:  'object'Œwi'Method'{param1}{param2}..."

[58]          Œwres„Œwres,Œtcnl,"param1:  parameter 1 description"

[59]          Œwres„Œwres,Œtcnl,"param2:  parameter 2 description"

[60]          Œwres„Œwres,Œtcnl,"Example: 'object'Œwi'Method'..."

[61]      :case'Method'

[62]

[63]      :else

[64]          Œwres„Œwi'*'

[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.

 

The Show, Wait and *Show, *Wait methods

 

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.

 


Collecting input data in your forms

 

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):

 

    ’ R„tt10;Z;NAME;Œwself

[1]   NAME„'Eric'

[2]   Œwself„'ff'Œwi'Create' 'TForm'

[3]       Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð Ð)('caption' 'Name')

[4]       Z„Œwi'.ed1.aplname' 'NAME'

[5]       Z„Œwi'.bnOK.Create' 'TOKButton'('wherelc' '=' '>' Ð Ð 0 20)

[6]       Z„Œwi'Wait'

[7]   R„NAME

    

 

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.

 


Knowing how a form has been closed

 

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:

 

    ’ R„tt11;Z;NAME;Œwself

[1]   NAME„'Eric'

[2]   Œwself„'ff'Œwi'Create' 'TForm'

[3]       Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð Ð)('caption' 'Name')

[4]       Z„Œwi'.ed1.aplname' 'NAME'

[5]       Z„Œwi'.bnOK.Create' 'TOKButton'('wherelc' '=' '>' Ð Ð 0 20)

[6]       Z„Œwi'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 Ð Ð

 

Updating our T_MyForm object to collect input data

 

Here is how you should write an application to call the T_MyForm object and collect data input.

 

    ’ R„tt12;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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'T_MyForm"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]          Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[20]          Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '='Ð 100)('caption' 'First Name')

[21]          Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '='Ð 200)('caption' 'Country')

[22]          Z„Œwi'.ed5.Create' 'TEdit'('wherelc' '>' '='Ð '=')('caption' 'Age')

[23]          Z„Œwi'.ed1.aplname' 'NAME'

[24]          Z„Œwi'.ed2.aplname' 'FNAME'

[25]          Z„Œwi'.ed4.aplname' 'COUNTRY'

[26]          Z„Œwi'.ed5.aplname' 'AGE'

[27]          Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)

[28]          Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[29]

[30]  :case'Action'

[31]      :select†Œwarg

[32]      :case'class'

[33]          Œwres„'T_MyForm'

[34]

[35]      :else

[36]          Œwres„Œwi'*'

[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||

|   '------''----''---''---'|

'¹--------------------------'

 


Data types

 

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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'T_MyForm"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]          Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[20]          Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '='Ð 100)('caption' 'First Name')

[21]          Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '='Ð 200)('caption' 'Country')

[22]          Z„Œwi'.ed5.Create' 'TEdit'('wherelc' '>' '='Ð '=')('caption' 'Age')

[23]          Z„Œwi'.ed1.aplname' 'NAME'

[24]          Z„Œwi'.ed2.aplname' 'FNAME'

[25]          Z„Œwi'.ed4.aplname' 'COUNTRY'

[26]          Z„Œwi'.ed5.aplname' 'AGE'

[27]          Z„Œwi'.ed5.type' 'positiveinteger'

[28]          Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)

[29]          Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[30]

[31]  :case'Action'

[32]      :select†Œwarg

[33]      :case'class'

[34]          Œwres„'T_MyForm'

[35]

[36]      :else

[37]          Œwres„Œwi'*'

[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: 

  1. integer which allows the following characters to be typed in the field: Œtcbs,Œtcnl,'-0123456789'

  2. float which allows the following characters to be typed in the field: Œtcbs,Œtcnl,'-.E0123456789'

  3. positivefloat which allows the following characters to be typed in the field: Œtcbs,Œtcnl,'.E0123456789'

 

Data validation

 

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:

 

  1. field exit validations
    These validations should only concern the content of the active field as we exit from it.  Validation expressions should not include other fields than the active field.  There can be only one APL validation expression per field.  If the validation expression fails the focus is automatically returned to the field that the user was trying to exit from.

  2. form validations
    These validations my include several form fields.  The APL validation expressions may include several form fields.  This kind of validation is automatically performed as the form is closed.  There can be several form APL validation expressions.  If one of the validation expressions fails, the form refuses to close itself.

 

Control 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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'T_MyForm"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]          Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[20]          Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð 100)('caption' 'First Name')

[21]          Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')

[22]          Z„Œwi'.ed5.Create' 'TEdit'('wherelc' '>' '=' Ð '=')('caption' 'Age')

[23]          Z„Œwi'.ed1.aplname' 'NAME'

[24]          Z„Œwi'.ed2.aplname' 'FNAME'

[25]          Z„Œwi'.ed4.aplname' 'COUNTRY'

[26]          Z„Œwi'.ed5.aplname' 'AGE'

[27]          Z„Œwi'.ed5.type' 'integer'

[28]          Z„Œwi'.ed5.check' '(AGE<20)ŸAGE>65' '"You must enter an age between 20 and 65!"'

[29]          Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)

[30]          Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[31]

[32]  :case'Action'

[33]      :select†Œwarg

[34]      :case'class'

[35]          Œwres„'T_MyForm'

[36]

[37]      :else

[38]          Œwres„Œwi'*'

[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:

 

    ’ R„T_MyForm_CheckAge

[1]   R„AGE<20

[2]   R„RŸAGE>65

    

 

     Œwi'.ed5.check' 'T_MyForm_CheckAge' '"You must enter an age between 20 and 65!"'

 

Form wide validations

 

The syntax for defining form wide validations is the following:

 

      check„      ›'APL_Val_Expr1' '"Error Message 1"' 'field1'

      check„check,›'APL_Val_Expr2' '"Error Message 2"' 'field2'

      ...

      check„check,›'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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'T_MyForm"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]          Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[20]          Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '='Ð 100)('caption' 'First Name')

[21]          Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '='Ð 200)('caption' 'Country')

[22]          Z„Œwi'.ed5.Create' 'TEdit'('wherelc' '>' '='Ð '=')('caption' 'Age')

[23]          Z„Œwi'.ed1.aplname' 'NAME'

[24]          Z„Œwi'.ed2.aplname' 'FNAME'

[25]          Z„Œwi'.ed4.aplname' 'COUNTRY'

[26]          Z„Œwi'.ed5.aplname' 'AGE'

[27]          Z„Œwi'.ed5.type' 'integer'

[28]          Z„Œwi'.ed5.check' '(AGE<20)ŸAGE>65'

 '"You must enter an age between 20 and 65!"'

[29]          Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)

[30]          Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[31]          check„      ›'(COUNTRY­"USA")^(AGE<30)ŸAGE>55'

  '"Age must be between 30 and 55 for Americans!"'(A,'.ed5')

[32]          check„check,›'(COUNTRY­"France")^(AGE<25)ŸAGE>60'

  '"Age must be between 25 and 60 for French!"'(A,'.ed5')

[33]          Z„Œwi'check'check

[34]

[35]  :case'Action'

[36]      :select†Œwarg

[37]      :case'class'

[38]          Œwres„'T_MyForm'

[39]

[40]      :else

[41]          Œwres„Œwi'*'

[42]      :end

[43]  :else

[44]      Œerror'Unknown T_MyForm command: ',B

[45]  :end

    

 

      tt12

 

 

 

 


Fields that must be set

 

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]  Œio„1

[12]  :if 2¬Œnc'A' ª A„Œwself ª :end

[13]  :select B

[14]  :case'New'

[15]      Œwself„A Œwi'*Create' 'TForm'

[16]          C„'T_MyForm"Action"'

[17]          C„C,Œtcnl,Œwi'*onAction'                © inherit from TForm

[18]          Œwi'*onAction'C

[19]          Z„Œwi'.ed1.Create' 'TEdit'('wherelc'Ð 60 Ð 200)('caption' 'Name')

[20]          Z„Œwi'.ed2.Create' 'TEdit'('wherelc' '>' '=' Ð 100)('caption' 'First Name')

[21]          Z„Œwi'.ed4.Create' 'TEdit'('wherelc' '>' '=' Ð 200)('caption' 'Country')

[22]          Z„Œwi'.ed5.Create' 'TEdit'('wherelc' '>' '=' Ð '=')('caption' 'Age')

[23]          Z„Œwi'.ed1.aplname' 'NAME'

[24]          Z„Œwi'.ed2.aplname' 'FNAME'

[25]          Z„Œwi'.ed4.aplname' 'COUNTRY'

[26]          Z„Œwi'.ed5.aplname' 'AGE'

[27]          Z„Œwi'.ed5.type' 'integer'

[28]          Z„Œwi'.ed5.check' '(AGE<20)ŸAGE>65' '"You must enter an age between 20 and 65!"'

[29]          Z„Œwi'.ed1.must' ''

[30]          Z„Œwi'.bnOk.Create' 'TOKButton'('wherelc'('=',A,'.ed1')'>' Ð Ð 0 112)

[31]          Z„Œwi'.bnCancel.Create' 'TCancelButton'('wherelc' '>' '=' Ð Ð)

[32]          check„      ›'(COUNTRY­"USA")^(AGE<30)ŸAGE>55'

      '"Age must be between 30 and 55 for Americans!"' (A,'.ed5')

[33]          check„check,›'(COUNTRY­"France")^(AGE<25)ŸAGE>60'

      '"Age must be between 25 and 60 for French!"' (A,'.ed5')

[34]          Z„Œwi'check'check

[35]

[36]  :case'Action'

[37]      :select†Œwarg

[38]      :case'class'

[39]          Œwres„'T_MyForm'

[40]

[41]      :else

[42]          Œwres„Œwi'*'

[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:

 

      Z„Œwi'.ed1.must' '(enter your Last Name here)'

 

And changed the tt12 function as follows:

 

    ’ R„tt12;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.

 


APL+Win 3.6 Objects

 

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.

 


APL+Win 3.6 Objects are organized in Collections.

 

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


The parent of all objects

 

Object

Description

TObject

The parent of all other objects: include many useful properties and methods, therefore available from all other objects

 

The Common Dialog Box Collection

 

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

 


The Complex Windows Collection

 

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

 

The Graphics Collection

 

Object

Description

TGraphX

A 2D and 3D graphics object based on APL2000 GraphX product. Requires to own a copy of GraphX

 

The Grids Collection

 

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

 

The Help Collection

 

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.

 


The Interactive Collection

 

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

 

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

 


The Internet Collection

 

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

 

The Menu Collection

 

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

 

The Microsoft Collection

 

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

 

The Miscellaneous Collection

 

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

 

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

 

 

Inheritance

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"'

        C„C,Œtcnl,'TObj2"Action"'             © inherit from TObj2

        C„C,Œtcnl,'TObj3"Action"'             © inherit from TObj3

        Œwi'*onAction'C

 

(assuming that an instance of TObj1 has been created and is the current object).

 


TObject, the parent of all objects

 

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

 

 

APL+Win 3.6 Objects Interactive Functions

 

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

 

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:

 

    ’ R„A 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!'

      msg„msg,Œtcnl,Œtcnl,'You may use digits, the minus sign and'

      msg„msg,Œ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

 

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?'

 

 

The YesNo function

 

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

 

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?'

      msg„msg,Œ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

 

 

Requesting input from the user:  the Question function

 

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:

 

      :select†res„Question'Enter your Name'

      :case 1

          © user pressed Enter of clicked OK

          ...

      :case 2

          © user pressed Esc or clicked Cancel

          ...

      :end

 

The Password function

 

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 TInfo object

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.


The TExcel object

 

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

Initializing the TExcel object

 

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


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.

Formatting data

 

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')

 

 

Alignments

 

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'

 

Background colors

 

You may change background cell colors using the BackColor property:

 

      'ee'Œwi'Range' 'B3:B5;C2:H2'

      'ee'Œwi'BackColor'(192 192 192)

 

Fonts

 

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

 

 

Setting Column Width

 

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

 

Printing with TExcel

 

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.

Setting margins

 

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

 

Setting headers and footers

 

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'

 

Centering horizontally or vertically

 

You may call the CenterHorizontally and/or CenterVertically methods to horizontally or vertically center the pages to print.

 

Example:

 

      'ee'Œwi'CenterHorizontally'1

 

Calling Excel dialogs

 

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


Conclusion

 

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:

 

http://www.lescasse.com