20. Writing 4GL Statements : Call Statements : Using the Callframe Statement
 
Share this page                  
Using the Callframe Statement
The callframe statement transfers control from one frame or 4GL procedure to another frame. The frame or 4GL procedure in which the statement appears is known as the calling frame or procedure, and the frame to which control is passed is known as the called frame. A user-specified, called frame can call another frame, and so on.
When the callframe statement executes, Ingres displays the new frame, and control passes to it. Typically, a called frame displays its own menu operations. The menu might include an End operation that issues a return statement, as described below. An example of the simplest type of callframe statement is:
callframe start;
This statement passes control to the frame named Start.
The ability to display new frames is one of a forms application's principal advantages over other types of applications. It is easy to use 4GL statements to sequence through frames in any order, using 4GL conditional statements. The user can determine, at run time, the order in which the frames appear, depending on the values of the data on the form. A particular frame can include operations that call any one of a variety of other frames. For examples, see Sample 4GL Application.
Using a Pop-up Frame
As with messages and prompts, you have the option of displaying frames in a pop-up style. Callframe's with style clause allows you to override the form's VIFRED style definition. For example:
callframe newframe with style = popup 
  (startrow = floating) ;
The statement above displays the frame Newframe as a pop-up in floating position, that is, at the current cursor position (if there is room at this position).
You can also alter the full-screen display of a form, as in this example:
callframe newframe with style = fullscreen 
  (screenwidth = narrow);
Here, the optional parameter screenwidth changes the fullscreen style to the narrower of the screen widths that you set up for the frame in VIFRED. See Callframe for more on screen width options.
Passing Parameters
When you call a procedure, a user-specified frame, or a report frame, you can pass values to it by means of a parameter list. This provides a way for frames to share information. The called frame can use the information received from the calling frame. More importantly, the calling frame can place the called frame in a particular state, so that the user sees continuity between frames. You cannot pass parameters to QBF or graphics frames.
Values for the parameter list can be literals, they can be supplied from the fields or variables of the calling frame, or they can be supplied by database queries. When you pass a parameter, its value transfers to a corresponding element inside the called frame or procedure. In the called frame, all fields, including local variables declared inside parentheses following the initialize keyword, can receive parameter values.
The example below calls the Newframe frame and places values in the fields on its form Newform:
callframe newframe
    (newform.name = 'Doe, John'; 
    newform.id = :empnum);
The value in the calling frame's field Empnum is thus passed to Newframe's field Id. Because the called form is not the currently active form, prefix the field names in the called frame with the name of the form.
In addition to the simple initializations of fields in the called frame described above, the callframe statement can also pass a query as an argument to the new frame. In this case, the query does more than simply initialize the fields; it starts a loop much like an attached query or submenu. The called frame can include next statements to display subsequent rows of the query, just as in the case of an attached query.
Passing queries between frames gives 4GL applications a great deal of power. This feature allows several different frames to call one common frame with different queries. The called frame offers the same operations for each of the different queries. You can pass only one query to the called frame.
To pass data from the database into a called frame, use a select statement to assign values to simple fields or a table field on the called frame's form, as in the example below:
callframe newframe (newform =
    select projnum, projname
      from projinfo 
      where projnum = :projno);
In this example, the current frame calls Newframe, passing values from the Projinfo database table into a form named Newform. The where clause restricts the retrieval operation to a specific project number that appears in the current frame's Projno field.
Passing Complex Parameters
You cannot assign or easily copy data parameters such as arrays, records, tables, table fields, and forms. However, arrays and records can be passed to frames and 4GL procedures as keyword parameters. You can pass complex parameters to user-specified frames and 4GL procedures, but not to 3GL procedures, Report frames, and database procedures. As with simple data components in 4GL, you pass complex data components as parameters by name.
Unlike simple variables, this is implicitly by reference, because all access to complex parameters is by reference. Changes made to the complex parameters in the called frame or procedure are reflected in the variable in the calling frame or procedure. The byref() clause cannot be applied to complex variables.
The types of the parameters being passed and the receiving elements for complex data components must agree. You cannot pass records declared as type of form or type of tablefield to other forms or table fields, but only to other form- or table-based record types or arrays. You cannot pass a table field to another frame or procedure.
Passing Parameters to Report Frames
User frames written in 4GL can pass parameters to report frames. Parameters passed to fields on the "form for report" are displayed as initial values when the form is displayed.
If a parameter does not correspond to a field on the form, the parameter is simply passed on by the report frame when the report is run. Therefore, if no form or a form with no fields is associated with the report frame, all parameters passed to the report frame are passed directly to the report as parameters. For example:
dept_no := 2;
lname := 'Smith';
callframe reportframe (name = lname;
  deptno = dept_no);
If the report frame's form has the fields Name and Title, the Name field has the initial value "Smith" and the Title field is empty. If the user fills in "Manager" for the Title field and overwrites the Name field with "Blumberg," ABF issues the equivalent of the following operating system report writer call when the user runs the report:
report dbasename reportname 
  (name = 'Blumberg',
  title = 'Manager', deptno = 2)
Returning a Value from Callframe
When the called 4GL frame returns control to the calling frame, it can use the return statement to pass back a single value. Among many possibilities, you can use this to send back a status code, which the calling frame can then use in conditional processing. The value returned can be of any Ingres data type, but you must declare the data type in the ABF Edit a USER Frame Definition window, or the Vision Moreinfo about a USER Frame window, for the called frame.
The calling frame can assign the returned value to a field or hidden field by using the following variant of the callframe statement:
fieldname | variable := callframe newframe ... ;
The ellipsis represents the argument list, if any. In this way, the calling frame can get information (a status value, for instance) back from the frame it just called. This information can affect the further operation of the calling frame. For more details, see Returning to the Top Frame and Callframe.
Passing Parameters by Value or by Reference
Simple fields, local variables, or table-field columns in a table-field row can be passed as parameters to a called frame or procedure by value or by reference.
A parameter passed by value (the default) is not affected by any change made to the value by the called frame or procedure. The parameter can be any 4GL expression.
For example, if an integer field containing a value of 2 is passed by value to a procedure, the field still has a value of 2 when control returns from the procedure, whether or not the value of the corresponding data element changed.
A simple field, table-field column, or variable passed by reference, however, is affected by a change in the value of its corresponding parameter inside the called frame or procedure.
The argument can be either a simple field, a table-field column, or a simple local variable in the current frame. You can pass local variables declared in parentheses after the initialize keyword as well as those declared in the declare section. If the value in a field or variable is passed by reference and the value of its corresponding data element changes while the called frame or procedure is running, the field has the new value when control returns to the calling frame. This enables the calling frame to receive multiple values (in addition to the single return value).
To pass a simple field, table-field column, or variable by reference, you must precede it with the reserved word byref, as shown below:
byref (objectname)
Here, objectname is a field name, a table-field column name, or a variable name.
Records and arrays are always passed by reference; however, you must not use the byref() keyword with them.
The value for a field, table-field column, or variable passed by reference is not normally available to the calling frame or updated in the window of the calling frame until the current operation is complete. For example, if a menu operation passes a field by reference to a procedure and, on return from the procedure, continues with other statements, the field's value is not changed until all the statements in the menu operation are executed.
If you must change the value before the end of the operation, place a redisplay statement immediately after the callframe or callproc statement.