Differences Among the Frame-invoking Statements
Because the three frame-invoking statements behave differently with reference to the frame they call, they have many unique features. The following subsections describe the different aspects of the callframe, openframe, and gotoframe statements.
How You Can Transfer Control to a New Frame: Callframe Statement
The callframe statement opens a new active frame that blocks the calling frame (makes it inactive). The called frame has control until you close it and returns control to the calling frame with the return statement. After you return control to the calling frame, the calling frame becomes active again.
How You Can Return a Value from an Active Child to the Inactive Parent
One feature of the callframe statement is its ability to pass a return value from the called frame to the calling frame using the return statement.
When you use the return statement in a frame that was opened with the callframe statement, you can pass a single value back to the calling frame. This enables the calling frame to get information back from the frame that it called. For example, you can use the return statement to send back a status code, which the calling frame can then use in conditional processing.
When you issue the original callframe statement, you must specify a variable name to receive the return value. The syntax is:
variable = callframe framename ([parameterlist])
variable
Specifies any variable within the scope of the calling component, including a field variable or a local variable declared in the initialize or declare blocks. The data type of the variable must be compatible with the return value data type you specified when you created the frame with the OpenROAD Workbench.
Then, in the return statement, you must specify the return value. The syntax is:
return expression
expression
Specifies any variables, constants, or expressions from the called frame. The value of the expression must be appropriate for the return data type of the called frame.
For example, in the following callframe statement, id is an integer variable:
id = callframe fakeframe;
The following return statement passes the integer value back to the frame that issued the callframe statement:
return 33;
How You Can Pass Parameters Between an Active Child and Inactive Parent
Another feature of the callframe statement is its ability to pass parameters by reference and by value. To pass a parameter by value, simply specify the parameter name and assign a value to it in the parameter list of the callframe statement.
For example, in the following statement, int_var, ref_var, and array_var are all parameters; and 2, check_out_row, and videos are their assigned values, respectively:
callframe myframe (int_var = 2, ref_var =
check_out_row,array_var = videos);
When you pass a simple variable, such as int_var, by value, any changes that you make to its value in the called frame are not reflected in the calling frame. For example, if myframe changes int_var to a value of 10, this change is not visible to the frame that called myframe. When myframe closes, int_var still has a value of 2 in the calling frame.
In contrast, when you pass a parameter that references a 4GL object or an array variable by value, any changes that you make to the object identified by the variable are reflected in the calling frame. This is because both array variables and variables referencing 4GL objects (reference variables) are pointers. When you pass a pointer to a called frame, both the called and the calling frame have a pointer to the same object. Consequently, any changes to that object in the called frame are visible in the calling frame when the called frame closes.
To pass a parameter by reference, you use the byref keyword. The syntax is:
callframe framename (parameter = byref(variable)
{, parameter = byref(variable)})
The following code is an example of this syntax:
callframe myframe (number = byref(int_var),
check_rec = ref_var,
movies = byref(array_var));
This example passes two variables by reference, number and movies,
; and one variable by value, check_rec. Because the variable passed by value references a 4GL object, changes made to the object in the child frame are visible in the parent frame.
Because the simple variable, number, was passed by reference, it also displays changes to the parent that are made in the child. When you pass a simple variable, such as int_var, by reference, any changes made to the parameter in the called frame are reflected in the variable in the calling frame after the called frame closes. Passing simple variables by reference, therefore, gives you a way to pass multiple return values to a calling frame.
Using the byref keyword to pass a reference or array variable lets you reassign the variable (a pointer) to a different object in the called frame and have that reassignment visible in the calling frame. The previous example shows how the array_var parameter is passed to myframe by reference. Consequently, if myframe reassigns the movies array variable to point to a different object, when myframe closes, array_var in the calling frame will also point to the new object.
In all cases, no changes reflected in the calling frame are visible until the called frame closes. At this point, the variable in the calling frame is updated the same way it would be if you had used an assignment statement. That is, if there is a field associated with the variable, it does not display the new value until the current event block completes. To cause the value to be updated before the end of the event block, use the Flush method immediately after the callframe statement. For more information about the Flush method, see the Language Reference Guide.
How You Can Open Concurrent Frames: Openframe Statement
The openframe statement opens a second frame while keeping the calling frame active. Use the openframe statement when you want to create concurrent frames.
The frame that you open with an openframe statement is considered a child of the calling frame. OpenROAD automatically terminates the child frame when the parent frame terminates. For example, if the user closes the video_list frame, which calls the video_detail frame, OpenROAD also closes video_detail.
When you use the openframe statement, it is important to keep the active frames synchronized. When the frames are displaying shared data, you must ensure that any changes that the user makes in one frame are reflected in the other open frames. For example, if the user makes a change in a called frame, the called frame can send a user event to the calling frame to inform it of the change.
When you first open the frame with the openframe statement, you can send parameters as starting values for the new frame. After issuing the openframe statement, however, you must explicitly coordinate all subsequent communication between the frames. For more information about the process involved, see
Inter-Frame Communication Techniques.
How You Can Pass Parameters Between Active Frames
If you pass an object as a parameter to the opened frame, you are actually passing the pointer to the object rather than the object itself. Therefore, because both the parent and child frames have pointers to the same object, any changes made to the object by the child frame are reflected in the parent frame.
If the object is associated with a field in the child frame, OpenROAD does not display the new value in the field until the current event block in the parent frame completes. To cause the value to be updated before the end of the event block, use the Flush method immediately after the openframe statement. For more information about the Flush method, see the Language Reference Guide.
How You Can Communicate Between Open Frames
Because the calling frame remains open when a called frame is executed by an openframe statement, it is important that the calling frame be able to communicate with the child frame. Consequently, the openframe statement returns a reference variable of type FrameExec to the calling frame. For the calling frame to use this value, you must capture the FrameExec object of the child frame in a variable. The syntax is:
[FrameExec_var =] openframe framename ([parameterlist])
The calling frame can also use the returned FrameExec object with the SendUserEvent method to communicate with the child frame. For more information, see
Inter-Frame Communication Techniques.
How You Can Pass Control While Closing the Parent: Gotoframe Statement
The gotoframe statement closes the calling frame and opens a new frame that replaces the calling frame. OpenROAD transfers control to the called frame, and the user cannot return to the calling frame.
Because the gotoframe statement closes the calling frame and therefore does not return to it, it has no return value. You should use this statement when you do not want users to return to the calling frame; for example, when you want an interim frame that the user fills out between using one frame and another.
Because the frame invoked by the gotoframe statement replaces the calling frame, the parent frame of the calling frame now has a new child frame. The following is an illustration of this concept:
OpenROAD automatically terminates the child frame when the parent frame terminates. Therefore, if the user closes the calling frame's parent frame, OpenROAD automatically terminates the new child frame.
How Returning to a Closed Parent Works
You cannot return to the calling frame (the frame that issued the gotoframe statement). However, you can use the return statement to return to the parent of the calling frame. You can specify an expression in the return statement if the data type of the parent frame's return type matches that of the child.
How You Can Pass Parameters Between an Active Child and a Closed Parent
Because passing a 4GL object as a parameter means passing the reference to the object rather than the object itself, even though gotoframe closes the calling frame, the reference variable on the called frame still points to the original object. It may not be useful, however, to pass a field object from the form on the calling frame because that field is no longer displayed.