When we create and use Calculation items, CalcIt provides automatically a Form to enter values for its parameters, execute the underlay Expression code and display the generated result. For simple calculation applications, that usually return a single value, this has to be adequate.
Form variables bring the ability for the CalcIt user to create his/her own custom Forms and completely control their functionality. This promotes the use of CalcIt much farther than for simple calculation or monolithic text processing purposes. Additionally the ability to create standalone CalcIt executable files makes the creation and use of custom Forms an unavoidable necessity.
To use Forms we need to successfully accomplice three simple tasks:
Before we create and use a Form we have to define its layout: How the Form looks like? What dimensions it has? Where in the desktop is positioned? What controls, that accept user input, incorporates? We create Form layouts using the command FORMDef.
FormDefID:=FORMDef(X, Y, W, H, Title, Properties List, Controls Definition list);
ControlCommand(static
parameters, Properties List, Controls
Definition List)
Static parameters are not the same for all Controls but at list ControlID is common to all of them and most of them have a parameter that defines the top and left positioning of Control inside the Form. E.g. look the command for the BUTTON Control:
ctrBUTTON(ID, X, Y, W, H, Text,Properties List)
Note that all Control commands share a common prefix of ctr. Static parameters, as in the Form itself, represent a number of properties that can be appear also in the Properties List and the only reason for their existence is to shorten the FORMDef statement. But not all Controls can contain a Controls Definition List. A Control must be able to contain other Controls (like the Form) to be able to have such a parameter. So Controls that can act as containers of other Controls are:
ctrGROUPBOX, ctrPAGE, ctrPANEL, ctrTABPAGE.
For every Control, as said before, there is at least one common parameter in its definition. This is the Control's ID. This ID has to be unique across all Controls in the Form because it is used to distinguish it in various operations.
FORMDef returns an ID that can be used to create Form variables based on the layout it represents. Will see more on this at Creating Form variables.
An example of how a Form layout definition looks like:
const fid=FORMDef(400,200,230,250,'Euro
Conversions',
ctrLABEL
('ID1',010,000,'Change
in Euro'),
ctrPANEL
('ID2',010,016,205,40),
ctrLEDIT
('ID3',010,080,100,'Product
Price (Euro)'),
ctrLEDIT
('ID4',115,080,100,'In Drachmas'),
ctrLEDIT
('ID5',010,140,205,'Payment
in Drachmas'),
ctrBUTTON('ID6',060,180,100,30,'Calculate')
);
CalcIt provides a simple but effective Visual Form Designer to create Form definition statements fast without dealing much with their details. You use drag and drop to put controls in a form where you can define many of their properties. Prefer to use this tool than making the job by hand. See specific topic.
Note that FORMDef is a compile time only command. That means that is not executed at run time but completely is evaluated at compile time, before the execution of the code. For this to be possible all of its parameters must be able to be evaluated at compile time and consequently can only be constants. Expressions can be used if they contain only constants values because such expressions are evaluated at compile time and finally return a constant value. So, because the returned ID is generated at compile time it can be assigned to a constant, as in the example above. Assigning this ID to a constant is also the recommended way to handle it.
When we have acquire an ID for a layout is time to create a Form that really permits entering of data. It's time to create a Form variable:
set frm=FORM(FormDefID, InstanceID,
CenterInScreen, Title, EventProc);
In the above example the frm Form variable is created. FormDefID is the value returned by a FORMDef command. InstanceID is any value the user chooses to identify the instance of the Form he/she creates. If there are more than one Forms in a code, this Instance ID has to be unique. For the rest of the parameters see at the Alphabetical Keywords List as will not interest us in this discussion.
After the execution of this command an instance of the requested Form layout is created. Through frm variable is now possible to handle the created Form and the Controls it contains. We handle a Form accessing for read or write its properties (like its Top position or its Title) and the properties of the Controls that may contain. Also, because the purpose of the Form is the interaction that a user can have with it, constantly his/her actions generate Events, like moving the mouse over the Form, entering text, clicking a Control etc. Also Controls and Forms can have a number of functions that can be used in the code to affect their operation, like to delete a row from a GRID control.
To access a property or use a function of the Form or one of its Controls the Form variable created as described above is used. For the Form itself follows a DOT and the name of property or function. For any of its Controls follows a expression enclosed in parentheses which returns Control's ID and, after the DOT, the name of property or function. See example below:
frm.Top:=100;
//Modifies the Top property of the Form
frm('ID1').Top:=20; //Modifies the Top property of the Control with ID='ID1'
To respond in events generated from Controls or the Form the user has to create in his/her code one local function with specific name and interface.
function EventProc(FormID, ControlID, Action, &Data);
Especially for use inside EventProc there is a syntax to create Form variable aliases using the Form ID (or instance ID) of the Form created previously in our code.
set frm=FORM(FormDefID,100);
function EventProc(FormID, ControlID, Action, &Data);
set AliasFrm=FORMID(100);
...
...
end;
In the code above global variable frm and AliasFrm are equivalent. They handle the same Form in the same way but with a different variable name. FORMID command can simplify programming in some situations and also is the only way to access Form variables declared locally in local functions:
function ShowAForm;
set frm=FORM(FormDefID,100);
ShowForm(frm);
end;
function EventProc(FormID, ControlID, Action, &Data);
set f=FORMID(100);
...
...
end;
In the above code the local variable frm in function ShowAForm cannot be accessible in EventProc in other way than the use of FORMID command.
Form Properties & EventsThe Form itself, like the Controls it can contain, has some Properties and fires some Events. Some of them are defined in the five first static parameters of the FORMDef command (Left, Top, Width, Height, Title). In the Properties List that follows the rest of them can also defined. All these are applied at the Form definition level. At run time a syntax through the Form variable is used. This was described in the above section: FormVar.PropertyName. Here is a list of Form Properties and Events:
Properties:
ACTIVECTRL, BORDER, BORDERWIDTH, COLOR, ENABLED, FONTBOLD, FONTCHARSET, FONTCOLOR, FONTNAME, FONTSIZE, HEIGHT, HINT, LEFT, TEXT, TOP, VISIBLE, WIDTH
Functions:
CLOSEFORM, SHOWFORM, WINHANDLE
Events:
OnClick, OnClose, OnMouseMove, OnTimer
When a code creates a Form possibly is not desirable to have the CalcIt windows appear behind. In this case we use the command Hide to hide them. When the code finishes the CalcIt windows reappear automatically. We can redisplay CalcIt windows again using Show command in our code, for example to see the Scratchpad window where possibly our code outputs data.
If we create a Form in our code and also hide CalcIt windows, is not possible to see the output of PRINT, PRINTARR. If we use these commands and want to see their output then we use SetOutput to redirect output in any Memo control in our Form.
SetOutput(frm,MemoControlID);
The above statement redirects the output of PRINT, PRINTARR to a MEMO control with MemoControlID in the Form instance handled via the variable frm. Note that only MEMO/RTFMEMO controls are accepted by this operation.
The contents of the currently selected as output ctrMEMO or ctrRTFMEMO control, can be printed trough TOPRINTER command.
Here is the list of all available Controls. Click on any item of the list to find a description for the Control, the properties it supports, the functions that may has and the events it generates.
ctrBUTTON, ctrCHART, ctrCHECKBOX, ctrCHECKLISTBOX, ctrCODEEDIT, ctrCOMBOBOX, ctrEDIT, ctrGRID, ctrGROUPBOX, ctrLABEL, ctrLEDIT, ctrLISTBOX, ctrMEMO, ctrPAGE, ctrPANEL, ctrRADIOBUTTON, ctrRTFMEMO, ctrSPLITTER, ctrTABPAGE, ctrTRACKBARA list of all Properties of all Controls and Form
ACTIVECTRL, ACTIVEPAGE, ALIGN, ALIGNMENT, ASKFORDEL, BEVELED, BEVELINNER, BEVELOUTER, BEVELWIDTH, BORDER, BORDERWIDTH, CELL, CHART3D, CHARTDATA, CHARTTYPE, CHECKED, COL, COLALIGN, COLCOUNT, COLOR, COLSIZING, COLWIDTH, DEFAULTCOLW, DEFAULTROWH, DROPCOUNT, ENABLED, FIXCOL, FIXCOLOR, FIXROW, FONTBOLD, FONTCHARSET, FONTCOLOR, FONTNAME, FONTSIZE, FREQUENCY, HEIGHT, HINT, HORZLINE, ITEMINDEX, LABELPOSITION, LABELTEXT, LEFT, LEGEND, LENGTH, LINE, LINEWIDTH, LISTITEMS, MARKS, MAX, MIN, NAME, NUMERIC, ORIENTATION, PACK, PAGEINDEX, POSITION, READONLY, ROW, ROWCOUNT, ROWHEIGHT, ROWINSERTS, ROWSELECT, ROWSIZING, SCROLLBARS, SLIDERSIZE, TEXT, TOP, VERTLINE, VISIBLE, WIDTH, WORDWRAP
A List of all function used by Controls or Form
CLEARROW, CLOSEFORM, COUNT, DELETEROW, EMPTYROW, INSERTROW, LINESCOUNT, MOVEROW, SELECTED, SETOUTPUT, SHOWFORM, SWAPROWS, WINHANDLE
A List of all Events generated by Controls and Form
OnAfterDel, OnAfterIns, OnChange, OnClick, OnClose, OnKeyPress, OnMouseMove, OnTimer, OnValidValue
The code below implements a simple text editor.
const fid= FORMDef(10,10,562,514,'Example Editor', ctrPANEL('ID1',0,0,556,447,prALIGN=alCLIENT,prBORDERWIDTH=2, ctrMEMO('ed',3,3,550,441,'',prALIGN=alCLIENT,prBORDER=bsNONE,prFONTNAME='Courier New',prFONTSIZE=10,prSCROLLBARS=ssBOTH,prWORDWRAP=FALSE)), ctrPANEL('ID2',0,447,556,41,prALIGN=alBOTTOM,prBORDERWIDTH=2, ctrBUTTON('load',11,8,75,25,'Load'), ctrBUTTON('save',100,8,75,25,'Save'), ctrBUTTON('exit',189,8,75,25,'Exit',prFONTBOLD=TRUE))); FName:=''; set f=FORM(fid,100,true); ShowForm(f); function EventProc(FrmID,CtrID,EventID,&Data); Select case(EventID=OnClick and CtrID eq 'load'); FName:=SelectFile('','Text Files (*.txt)|*.txt'); if(FName ne ''); set r=READ(FName); f('ed').Text:=Arr2Text(r); end; case(EventID=OnClick and CtrID eq 'save'); if(FName eq ''); FName:=GetSaveFile('','Text Files (*.txt)|*.txt'); end; if(FName ne ''); Text2Arr(f('ed').Text,r); Write(FName,r); end; case(EventID=OnClick and CtrID eq 'exit'); CloseForm(f); end; end;