Questions and Answers | Tutorial - Creating a Sample Screenset |
This chapter contains sample dialog for the following objects:
It also contains the following sample programs:
Entry fields are described in detail in the chapter Control Objects. This section describes dialog required to:
Entry fields are validated with the VALIDATE function. If validation fails, the VAL-ERROR event is triggered. You can validate an entry field explicitly:
VALIDATE AMOUNT-DEPOSITED-EF
Or you can validate an entry field implicitly by validating the parent window. For example:
VALIDATE DEPOSIT-WIN
The recommended way is to validate the field implicitly when the user accepts data on the window or dialog box that contains the field (for example the user presses OK or Enter). This lets the user enter the information, review it, and correct it if necessary before the validation. If the validation fails, you can set the focus back on the field with the error.
1 BUTTON-SELECTED 2 VALIDATE $WINDOW 3 INVOKE-MESSAGE-BOX ERROR-MB "All fields OK" $REGISTER 4 RETC 5 VAL-ERROR 6 INVOKE-MESSAGE-BOX ERROR-MB ERROR-MSG-FIELD $REGISTER 7 SET-FOCUS $EVENT-DATA
BUTTON-SELECTED
In this example, validation is activated by selecting a push button. Validation could also be activated by the window losing focus or a particular field losing focus using the LOST-FOCUS event. For example, focus is lost by the current control when the user uses the Tab key to move to another control.
VALIDATE $WINDOW
This statement validates all fields on the current window according to the validation criteria you set up. If Dialog System detects an error, the VAL-ERROR event is triggered. If no error is detected, Dialog System continues as normal and executes the next function.
INVOKE-MESSAGE-BOX ERROR-MB "All fields OK" $REGISTER RETC
The VAL-ERROR event did not occur. Invoke a message box informing the user that no errors were detected and return to the program.
VAL-ERROR
The VAL-ERROR event is detected. The special register $EVENT-DATA identifies the entry field that failed validation.
INVOKE-MESSAGE-BOX ERROR-MB ERROR-MSG-FIELD $REGISTER
Notify the user of the error using a message box.
The second parameter, ERROR-MSG-FIELD
, contains the
error message defined for this validation error. ERROR-MSG-FIELD
is defined as the error message field in the data definition.
The following dialog illustrates one way of coding the validation step. The dialog is attached to a push button.
SET-FOCUS $EVENT-DATA
Put the input focus back on the entry field that failed the validation.
Warning: You can validate the field when the user tries to move off it by using the LOST-FOCUS event . However, if the validation fails and you set the focus on the field, the focus always returns to the field whenever the user tries to put the focus on another application. It is better to validate the whole window.
The procedures described in the previous section handle simple data validation. Sometimes, more complex validation than Dialog System can provide is needed. For example, the range of a valid credit limit often depends on the number of years a customer has been with a company.
This type of cross-field validation requires intervention because either you need data that is not contained in your screenset, or the validation is more sophisticated than the validation rules provided by Dialog System. You need to return to the calling program to do this type of checking.
See the chapter Advanced Topics for an example.
You can move text to an associated data item using either your application program or dialog.
An example of moving text to an associated data item in your application program is the statement:
move "Now is the time..." to large-entry-field
This moves the string to the Data Block item that is associated with the MLE.
You can insert line feeds by using the hexadecimal character "0a". For example:
move "line1" & x"0a" & "line2"
where:
line1 and line2 |
are the text to be displayed on separate lines. |
& |
concatenates the character strings. |
x |
indicates a hexadecimal character. |
0a |
is the hexadecimal character for a line feed. |
In this case, line feeds cannot be inserted. For example, use the following statement in dialog:
move "Now is the time..." large-entry-field
where large-entry-field
is the data item associated with
the MLE.
This section covers samples of dialog for:
1 BUTTON-SELECTED 2 DISABLE-OBJECT $CONTROL 3 ENABLE-OBJECT CONTINUE-PB 4 BRANCH-TO-PROCEDURE PAUSE-SELECTED
BUTTON-SELECTED
The user selects the Pause button, which triggers the BUTTON-SELECTED event. This event is the primary event associated with a push button.
DISABLE-OBJECT $CONTROL
$CONTROL
is a special register that identifies the currently selected
control. This function disables the current control (in this case, the
Pause push button). This means the button is unavailable to the
user.
ENABLE-OBJECT CONTINUE-PB
This statement enables the Continue push button. This means this
button becomes available for the user to select. CONTINUE-PB
is the name of the push button that you assigned to the push button in the
Push Button properties window.
BRANCH-TO-PROCEDURE PAUSE-SELECTED
The functions in the PAUSE-SELECTED procedure are performed. In this procedure you can, for example, set a flag and return to the calling program.
For information on defining a push button, see the chapter Control Objects.
The following fragment of dialog illustrates one way to change dynamically the bitmaps assigned to a push button.
Note: Before you can use bitmaps, you must make them available to Dialog System. See the chapter Control Objects for further information.
1 ... 2 @SAVE 3 BRANCH-TO-PROCEDURE SAVE-FUNCTION 4 SAVE-FUNCTION 5 SET-OBJECT-LABEL GENERIC-PB SAVE-STATES 6 SET-FOCUS GENERIC-WIN 7 ...
@SAVE BRANCH-TO-PROCEDURE SAVE-FUNCTION
The user selected the Save option from a menu. Branch to the procedure that does the save function.
SET-OBJECT-LABEL GENERIC-PB SAVE-STATES
GENERIC-PB
is the name assigned to the push button. SAVE-STATES
is an alphanumeric data item large enough to hold the names of the
replacement bitmaps and three null characters (x"0A").
SET-FOCUS GENERIC-WIN
Set the keyboard focus to the window, so that all objects in the window are refreshed, and continue.
In your program, fill save-states
in the Data Block using
a statement like:
move "save-normal" & x"0A" & "save-disabled" & x"0A" & "save-depressed" & x"0A" to save-states.
where save-normal
, save-disabled
, and
save-depressed
are the names of the bitmaps that are
displayed depending on the state of the push button. The order you assign
the names is important.
The first name is the bitmap that is displayed when the push button is in the "normal" state. The second name is the bitmap displayed when the push button is disabled. The third name is the bitmap displayed when the push button is pressed.
Check boxes are described in detail in the chapter Control Objects. The Objects sample program shows an example of using check boxes.
This example shows you how to select one or more of the products from a list and display the items in a list box by clicking a Display push button. See Figure 17-1.
Figure 17-1: Check Boxes With List Box
The data definitions for this sample screenset are:
1 WORKBENCH 9 1.00 2 TOOLSET 9 1.00 3 COBOL 9 1.00 4 DIALOG-SYSTEM 9 1.00 5 PRODUCTS 4 6 PRODUCT-DISPLAY X 15.00
Data items 1 to 4 are the data items associated with the corresponding check boxes. Data items 5 and 6 are used for the list box that displays the selected items.
The dialog (attached to the Display push button) for controlling this example is:
1 BUTTON-SELECTED 2 MOVE " " PRODUCT-DISPLAY(1) 3 MOVE " " PRODUCT-DISPLAY(2) 4 MOVE " " PRODUCT-DISPLAY(3) 5 MOVE " " PRODUCT-DISPLAY(4) 6 MOVE 1 $REGISTER 7 IF= WORKBENCH 0 CHECK-TOOLSET 8 MOVE "Workbench" PRODUCT-DISPLAY($REGISTER) 9 INCREMENT $REGISTER 10 BRANCH-TO-PROCEDURE CHECK-TOOLSET 11 12 CHECK-TOOLSET 13 IF= TOOLSET 0 CHECK-COBOL 14 MOVE "Toolset" PRODUCT-DISPLAY($REGISTER) 15 INCREMENT $REGISTER 16 BRANCH-TO-PROCEDURE CHECK-COBOL 17 18 CHECK-COBOL 19 IF= COBOL 0 CHECK-DIALOG-SYSTEM 20 MOVE "COBOL" PRODUCT-DISPLAY($REGISTER) 21 INCREMENT $REGISTER 22 BRANCH-TO-PROCEDURE CHECK-DIALOG-SYSTEM 23 24 CHECK-DIALOG-SYSTEM 25 IF= DIALOG-SYSTEM 0 DISPLAY-PRODUCTS-DB 26 MOVE "Dialog System" PRODUCT-DISPLAY($REGISTER) 27 BRANCH-TO-PROCEDURE DISPLAY-PRODUCTS-DB 28 29 DISPLAY-PRODUCTS-DB 30 REFRESH-OBJECT CHECKB-LB 31 SET-FOCUS CHECKB-DB
BUTTON-SELECTED
The user selected the Display push button .
MOVE " " PRODUCT-DISPLAY(1) MOVE " " PRODUCT-DISPLAY(2) MOVE " " PRODUCT-DISPLAY(3) MOVE " " PRODUCT-DISPLAY(4)
Initialize the list box items, by moving a blank string to the items in
the PRODUCT-DISPLAY
group.
MOVE 1 $REGISTER
Initialize the index ($REGISTER) . $REGISTER is an internal register that you can use to store a numeric value. In this case, use it as an index into the list box.
IF= WORKBENCH 0 CHECK-TOOLSET
If the Workbench check box has not been checked, branch to the procedure that checks if the Toolset check box has been checked. If the Workbench check box has been checked, continue to the next function and do not branch.
MOVE "Workbench" PRODUCT-DISPLAY($REGISTER) INCREMENT $REGISTER
To get here, the user selected the Workbench check box. Fill the list box data item and increment the index.
BRANCH-TO-PROCEDURE CHECK-TOOLSET
Branch to the procedure that checks the Toolset check box.
CHECK-TOOLSET IF= TOOLSET 0 CHECK-COBOL MOVE "Toolset" PRODUCT-DISPLAY($REGISTER) INCREMENT $REGISTER BRANCH-TO-PROCEDURE CHECK-COBOL CHECK-COBOL IF= COBOL 0 CHECK-DIALOG-SYSTEM MOVE "COBOL" PRODUCT-DISPLAY($REGISTER) INCREMENT $REGISTER BRANCH-TO-PROCEDURE CHECK-DIALOG-SYSTEM CHECK-DIALOG-SYSTEM IF= DIALOG-SYSTEM 0 DISPLAY-PRODUCTS-DB MOVE "Dialog System" PRODUCT-DISPLAY($REGISTER) BRANCH-TO-PROCEDURE DISPLAY-PRODUCTS-DB
This is similar dialog for the other check boxes.
DISPLAY-PRODUCTS-DB REFRESH-OBJECT CHECKB-LB SET-FOCUS CHECKB-DB
Display the selected products in the list box.
You can update items in a list box in three ways:
You can associate the list box with a group item, so that each line in the list box displays an occurrence of the group. Selected items in the group then occupy fields in each line.
The sample application Saledata illustrates this method of accessing a list box. Using an existing file, the application loads a set of sales data to a group item (SALES-GROUP) in the Data Block. The list box (SALES-LB) displays the data. Then you can update (insert, change, delete) entries or view the set of data in different sort orders.
This Data Block section defines the data referenced in the following dialog:
SALES-GROUP 100 SALES-NAME X 20.00 SALES-REGION X 4.00 SALES-STATE X 2.00 TMP-NAME X 20.00 TMP-REGION X 4.00 TMP-STATE X 2.00 NUMBER-OF-RECORDS 9 3.00
The following portions of dialog are those dealing with the list box:
1 SET-DATA-GROUP-SIZE SALES-GROUP NUMBER-OF-RECORDS 2 ... 3 ITEM-SELECTED 4 MOVE $EVENT-DATA $REGISTER 5 ... 6 PROC-INSERT 7 INSERT-OCCURRENCE SALES-GROUP $REGISTER 8 MOVE TMP-NAME SALES-NAME($REGISTER) 9 MOVE TMP-REGION SALES-REGION($REGISTER) 10 MOVE TMP-STATE SALES-STATE($REGISTER) 11 INCREMENT NUMBER-OF-RECORDS 12 INCREMENT $REGISTER 13 REFRESH-OBJECT SALES-LB 14 SET-LIST-ITEM-STATE SALES-LB 1 $REGISTER 15 ... 16 PROC-CHANGE 17 MOVE TMP-NAME SALES-NAME($REGISTER) 18 MOVE TMP-REGION SALES-REGION($REGISTER) 19 MOVE TMP-STATE SALES-STATE($REGISTER) 20 UPDATE-LIST-ITEM SALES-LB SALES-GROUP $REGISTER 21 SET-LIST-ITEM-STATE SALES-LB 1 $REGISTER 22 ... 23 PROC-DELETE 24 DELETE-OCCURRENCE SALES-GROUP $REGISTER 25 DECREMENT NUMBER-OF-RECORDS 26 DECREMENT $REGISTER 27 REFRESH-OBJECT SALES-LB 28 SET-LIST-ITEM SALES-LB 1 $REGISTER
SET-DATA-GROUP-SIZE SALES-GROUP NUMBER-OF-RECORDS
This statement defines the internal size of the data group. This is the number of occurrences of a group that you can access. Refer to the description of the SET-DATA-GROUP-SIZE function in your help for a complete definition of internal size.
ITEM-SELECTED MOVE $EVENT-DATA $REGISTER
You can browse the list box until you find the item you want to select. The ITEM-SELECTED event is triggered when the item (list box row) is selected. The special event register $EVENT-DATA contains the row number of the item selected. Use $REGISTER to keep track of the current location in both the group data and the list box.
PROC-INSERT
This procedure inserts an item in the position now occupied by the selected item.
INSERT-OCCURRENCE SALES-GROUP $REGISTER
Insert a blank occurrence into the data group at the specified location. The selected item and all items following are moved down one row. The list box is not affected. This function only updates the data group.
MOVE TMP-NAME SALES-NAME($REGISTER) MOVE TMP-REGION SALES-REGION($REGISTER) MOVE TMP-STATE SALES-STATE($REGISTER)
Update the group item with the new information.
INCREMENT NUMBER-OF-RECORDS
Increment the number of records in the data group.
INCREMENT $REGISTER
Update the pointer to the current row. This keeps the pointer addressing the same row it was before the insertion.
REFRESH-OBJECT SALES-LB
A list box associated with a group item must be refreshed before it reflects changes in the data. The INSERT-OCCURRENCE and DELETE-OCCURRENCE functions have no effect on a list box. If you have only one entry in the list box that needs to be refreshed, you can use the UPDATE-LIST-ITEM function. However, in the case of an insertion, all rows in the data group after the insertion row are changed. It is better to use the REFRESH-OBJECT function.
SET-LIST-ITEM-STATE SALES-LB 1 $REGISTER
Change the state of the current row to "selected" . This is the same row that was selected before the insertion.
PROC-CHANGE
This procedure changes the contents of the selected item.
MOVE TMP-NAME SALES-NAME($REGISTER) MOVE TMP-REGION SALES-REGION($REGISTER) MOVE TMP-STATE SALES-STATE($REGISTER)
Update the group item with the new information.
UPDATE-LIST-ITEM SALES-LB SALES-GROUP $REGISTER
Because only one row in the list box changed, you can use the UPDATE-LIST-ITEM function. You do not have to refresh the entire list box since all other rows remain the same.
SET-LIST-ITEM-STATE SALES-LB 1 $REGISTER
Change the state of the current row to "selected". This is the same row that was selected before the change.
DELETE-OCCURRENCE SALES-GROUP $REGISTER
Delete the occurrence from the data group at the selected location. All items following are moved up one row.
DECREMENT NUMBER-OF-RECORDS
Decrement the number of records in the data group.
DECREMENT $REGISTER
Update the pointer to the current row. This keeps the pointer addressing the same row.
REFRESH-OBJECT SALES-LB
Refresh the list box.
SET-LIST-ITEM SALES-LB 1 $REGISTER
Change the state of the current row to "selected". This is the row following the one that was deleted.
You can also maintain items in a list box at run time using the dialog functions INSERT-LIST-ITEM, UPDATE-LIST-ITEM, and DELETE-LIST-ITEM .
For example, the following dialog fragment is one way to add the
abbreviations for months to a list box named MONTH-LB
.
SCREENSET-INITIALIZED INSERT-LIST-ITEM MONTH-LB "Jan" 1 INSERT-LIST-ITEM MONTH-LB "Feb" 2 INSERT-LIST-ITEM MONTH-LB "Mar" 3 INSERT-LIST-ITEM MONTH-LB "Apr" 4 INSERT-LIST-ITEM MONTH-LB "May" 5 INSERT-LIST-ITEM MONTH-LB "Jun" 6 INSERT-LIST-ITEM MONTH-LB "Jul" 7 INSERT-LIST-ITEM MONTH-LB "Aug" 8 INSERT-LIST-ITEM MONTH-LB "Sep" 9 INSERT-LIST-ITEM MONTH-LB "Oct" 10 INSERT-LIST-ITEM MONTH-LB "Nov" 11 INSERT-LIST-ITEM MONTH-LB "Dec" 12
This is an effective way of populating a list box if you have a few choices in your list and you want to keep the Data Block as small as possible. Although it does not require much time to fill a small list box this way, it does take a little time and does add to the number of dialog statements that have to be searched. The section How Dialog System Searches for Event Dialog in the chapter Using Dialog describes the rules for searching dialog.
As an alternative, the following dialog can be used:
SCREENSET-INITIALIZED INSERT-LIST-ITEM MONTH-LB "Jan" 0 INSERT-LIST-ITEM MONTH-LB "Feb" 0 INSERT-LIST-ITEM MONTH-LB "Mar" 0 INSERT-LIST-ITEM MONTH-LB "Apr" 0 INSERT-LIST-ITEM MONTH-LB "May" 0 INSERT-LIST-ITEM MONTH-LB "Jun" 0 INSERT-LIST-ITEM MONTH-LB "Jul" 0 INSERT-LIST-ITEM MONTH-LB "Aug" 0 INSERT-LIST-ITEM MONTH-LB "Sep" 0 INSERT-LIST-ITEM MONTH-LB "Oct" 0 INSERT-LIST-ITEM MONTH-LB "Nov" 0 INSERT-LIST-ITEM MONTH-LB "Dec" 0
A value of 0
for the third parameter tells Dialog System
to insert the data item at the end of the list.
Another way to insert a few items in a list box
is the INSERT-MANY-LIST-ITEMS
function using a data item passed from your program. For example,
the following dialog inserts the same month abbreviations into MONTH-LB
:
SCREENSET-INITIALIZED INSERT-MANY-LIST-ITEMS MONTH-LB MONTHS-STRING 48
where the parameters are:
MONTH-LB |
The name of the list box you defined in the List Box Properties dialog box. |
MONTHS-STRING |
A data item, passed from your program, with the
individual list items delimited by x"0A". It is defined in the
Data Definition facility as:
|
48 |
The number of characters to copy to the list box. See
the topic INSERT-MANY-LIST-ITEMS in the Help for more details
about this parameter. |
In the Working-Storage Section of your program, define the string as:
01 months. 03 pic x(4) value "Jan" & x"0A". 03 pic x(4) value "Feb" & x"0A". 03 pic x(4) value "Mar" & x"0A". 03 pic x(4) value "Apr" & x"0A". 03 pic x(4) value "May" & x"0A". 03 pic x(4) value "Jun" & x"0A". 03 pic x(4) value "Jul" & x"0A". 03 pic x(4) value "Aug" & x"0A". 03 pic x(4) value "Sep" & x"0A". 03 pic x(4) value "Oct" & x"0A". 03 pic x(4) value "Nov" & x"0A". 03 pic x(4) value "Dec" & x"0A".
Then move the string to the Data Block with a statement like:
move months to months-string
This section covers:
Two events are associated with a scroll bar; SLIDER-MOVING and SLIDER-RELEASED.
The SLIDER-MOVING event occurs when the slider has been moved to a new position.
For example, in the dialog to implement this feature:
1 SLIDER-MOVING 2 MOVE $EVENT-DATA COUNTER 3 REFRESH-OBJECT COUNTER-DISP 4 SLIDER-RELEASED 5 MOVE $EVENT-DATA COUNTER 6 REFRESH-OBJECT COUNTER-DISP
lines 1 to 3 display the position of the slider in the entry field
COUNTER-DISP
.
The SLIDER-RELEASED event occurs when the slider has been released. Lines 4 to 6 in the dialog use this event and also display the position of the slider. A complete description of this dialog is:
SLIDER-MOVING
The slider is moved to a new position.
This triggers the SLIDER-MOVING
event.
MOVE $EVENT-DATA COUNTER
When the slider is moved, the special register $EVENT-DATA
contains the new slider position. This position is expressed in
relation to the minimum and maximum values. COUNTER
is a
Data Block data item that is attached to the entry field COUNTER-DISP
.
REFRESH-OBJECT COUNTER-DISP
The entry field must be refreshed to reflect the new data value.
SLIDER-RELEASED
The slider is released at a new position.
This triggers the SLIDER-RELEASED
event.
MOVE $EVENT-DATA COUNTER
When the slider is released, $EVENT-DATA
contains the new
slider position. Again, COUNTER
is a Data Block data item
that is attached to the entry field COUNTER-DISP
.
REFRESH-OBJECT COUNTER-DISP
Refresh the entry field.
The scroll bar example in the sample application Objects shows how to use an entry field this way.
The Scroll Bar Properties dialog box enables you to assign defaults to scroll bar properties such as slider range, slider position and slider size. Using dialog, you can change these properties .
For example, this dialog fragment changes the properties of a scroll bar
named EMP-LIST-SB
.
SET-SLIDER-RANGE EMP-LIST-SB 0 50 SET-SLIDER-POSITION EMP-LIST-SB 25 SET-SLIDER-SIZE EMP-LIST-SB 5
Refer to the topic Dialog Statements: Functions in the Help for a full description of these functions.
For information on defining a scroll bar, see the topic Objects and Properties in the Help.
Pages can be inserted and deleted from a tab control using the COPY-PAGE and DELETE-PAGE functions. This enables the tab control to be maintained dynamically.
As an example, you could write an application which stored customer contact information such as address, contact history, and sales information. This information for each customer could be displayed in a tab control.
See Figure 17-2 below.
Figure 17-2: Sample Tab Control Page
If, for example, one page of sales information was not sufficient, you could add a second page as follows:
1 ADD-MORE-SALES-INFO 2 COPY-PAGE SALES-INFO-PAGE 0 2 3 SET-OBJECT-LABEL SALES-INFO-PAGE "Sales Information 2"
ADD-MORE-SALES-INFO
A procedure to add another sales information page to the tab control.
COPY-PAGE SALES-INFO-PAGE 0 2
COPY-PAGE makes a copy of the tab control page and inserts it in the
correct location in the tab control. SALES-INFO-PAGE
is the
name assigned to the page. The second parameter, 0
, is the
position to copy to; 0 means last, 1 means first. The third parameter
specifies the instance number for the page. The instance number overrides
the subscript of any entry fields with subscripted master fields that
appear on the page. Remember, however, that any pages you create in the
tab control will always appear unless you explicitly delete them (see
below).
SET-OBJECT-LABEL SALES-INFO-PAGE "Sales Information 2"
Changes the text in the tab on the new page. Note that after a
COPY-PAGE, SALES-INFO-PAGE
refers to the new page, not the
original.
To delete a page from a tab control, the DELETE-PAGE function is used. For example, if a customer had no sales information, you could delete the page as follows:
BUTTON-SELECTED DELETE-PAGE SALES-INFO-PAGE
See the Help for a detailed description of these functions.
Details about using the call interface can be found in the chapter Using the Screenset. This section covers:
Dsrnr is a sample subprogram supplied with Dialog System. To launch it:
runw dsrunner
The Dsrnr main window appears. You can load multiple instances of Dsrnr (you can have up to 32 screensets on the stack at any time) simply by opening it again. If you want, you can run the subprogram through the Animator.
Now let's take a detailed look at key sections of the sample code.
14 linkage section. 15 16* data block from screenset 17 copy "dsrnr.cpb". 18 19* (optional) dsrunner info and ds event blocks 20 copy "dsrunner.cpy". 21 copy "dssysinf.cpy".
You must copy the Data Block copyfile into your program to be able to access the screenset data. You can, optionally, also copy in the dsrunner copyfile that represents the linkage between Dsrunner and your subprogram, dsrunner.cpy. If you want to process Panels2 event information you also need to copy in dssysinf.cpy. Notice that these are copied into the linkage section because they are parameters of the subprogram.
24 procedure division using data-block 25 dsrunner-info-block 26 ds-event-block.
You must specify the data-block parameter. The other two parameters are optional. Use dsrunner-info-block if you want to be informed of errors. Use ds-event-block if you want to use Panels2 and Dialog System together.
27 main section. 28* Put out a message if we are run from the command line 29* instead of being called by DSRUNNER. 30 if (address of data-block = null) 31 display "This is a subprogram, and must be CALLed" 32* display "(Preferably from DSRUNNER)." 33 exit program 34 stop run 35 end-if
You need to check that the subprogram is being called and you can do that easily by checking that it is being passed a Data Block address.
37 move 0 to return-code 38 39* Determine if this is the first time we've been called with 40* this data block. We can do this by checking the data block 41* for low values, which is what DSRUNNER initialises all data 42* blocks with. 43 if (data-block = all low-values) 44* This is the first time we have been called with this 45* Screenset/Data-Block. Perform any initialisation, 46* and then exit. The screenset is not loaded (and no 47* SCREENSET-INITIALIZED event occurs) until after 48* we return from here. 49 perform initialisation 50 else 51* This is not the first time we have been called, 52* therefore do our normal handling. 53 perform handle-screenset-request 54 end-if 55 56 continue. 57 58 exit-main. 59 60 exit program 61 stop run.
Each time the subprogram is called as a new instance, it must perform any required initialization of the Data Block. Line 43 shows how to check if this is the first time the subprogram has been called with this Data Block (new instance of screenset). Once the subprogram has performed its initialization, you must return to Dsrunner. Dsrunner will call your program whenever a RETC occurs in the screenset associated with this subprogram.
64 initialisation section. 65* Perform any pre-screenset initialisation here. 66 67 initialize data-block 68 move dsrunner-screenset-instance to my-instance-no 69 70 continue.
Line 68 shows how the subprogram can find out its instance number.
73 handle-screenset-request section. 74* We end up here whenever the screenset does a RETC, or 75* a DSGRUN error has occurred, and DSRUNNER is calling us to 76* do any error handling before we get terminated. 77 78* Have we been called because our screenset caused an error? 79 if (dsrunner-error-code not = 0) 80* Yes, so handle it 81 perform handle-dsgrun-error 82 exit section 83 end-if 84* Have we been called because of a validation error? 85 if (dsrunner-validation-error-no not = 0) 86* Yes, so handle it 87 perform handle-validation-error 88 exit section 89 end-if 90 91* Must have been a normal RETC from our screenset, so 92* just service the screenset request. 93 94 move "successful" to program-string 95 96 evaluate reason-for-returning 97 when "+" 98 add program-value-1 to program-value-2 99 giving result-value 100 101 when "-" 102 subtract program-value-1 from program-value-2 103 giving result-value 104 105 when "*" 106 multiply program-value-1 by program-value-2 107 giving result-value 108 109 when "/" 110 divide program-value-1 by program-value-2 111 giving result-value 112 on size error 113 move "Bad result from divide" to program-string 114 115 when other 116 move "sorry, unsupported function" to program-string 117 118 end-evaluate 119 120 continue.
This section of code handles screenset requests following a RETC dialog function within the screenset associated with this subprogram.
Checks are made in line 79 and in line 85 to see if there has been a Dsrunner error or a validation error of some sort. If either error has occurred it is handled accordingly, otherwise the screenset request is handled.
123 handle-dsgrun-error section. 124* We end up here when a DSGRUN error occurs in the screenset. 125* In this example I am deciding to display the error message 126* myself. If this is the first time this has occurred, I 127* continue, otherwise I set the RETURN-CODE indicating that 128* DSRUNNER should terminate me. If the return-code is zero 129* DSRUNNER would continue as if nothing had happened. 130 131 move dsrunner-error-code to error-number 132 move dsrunner-error-details-1 to error-details1 133 move dsrunner-error-details-2 to error-details2 134 display "dsrnr: " 135 "dsgrun error " error-number 136 ", " error-details1 137 ", " error-details2 138 139 if (handle-error-count = 0) 140 add 1 to handle-error-count 141 else 142* This will force dsrunner to terminate me 143 move 1 to return-code 144 end-if 145 146 continue.
This section of code handles dsrunner errors.
Line 143 shows how to terminate Dsrunner by returning a non-zero return code.
149 handle-validation-error section. 150* We end up here when a screenset validation error has 151* occurred. Same rules apply here as for above. 152 153 move dsrunner-validation-error-no to error-number 154 155 display "dsrnr: validation error code ", error-number 156 157* This will force dsrunner to terminate me 158 move 1 to return-code 159 160 continue.
This section of code handles user input errors.
The following sample program, push-pop.cbl, demonstrates the use of the pushing and popping of screensets.
The COBOL programs, screensets, and associated files are included on your samples disk. Instructions for compiling and running these programs are given in the chapter Using the Screenset.
Push-pop uses three screensets:
A full listing of the program is provided below. An explanation of the functions used for pushing and popping is given after.
1 $SET ANS85 MF 2 3 working-storage section. 4 copy "ds-cntrl.mf ". 5 copy "pushmain.cpb ". 6 copy "filemgr.cpb ". 7 copy "printmgr.cpb ". 8 9 01 new-screenset-name pic x(12). 10 11 01 action pic 9. 12 78 load-file value 1. 13 78 load-print value 2. 14 78 exit-program value 3. 15 01 end-of-actions-flag pic 9. 16 88 end-of-actions value 1. 17 18 procedure division. 19 20 main-process. 21 perform program-initialize 22 call "dsgrun" using ds-control-block, 23 pushmain-data-block 24 perform process-actions until end-of-actions 25 stop run. 26 27 program-initialize. 28 initialize ds-control-block 29 initialize pushmain-data-block 30 move ds-new-set to ds-control 31 move pushmain-data-block-version-no to 32 ds-data-block-version-no 33 move pushmain-version-no to ds-version-no 34 move "pushmain" to ds-set-name 35 move zero to end-of-actions-flag. 36 37 process-actions. 38 evaluate true 39 when pushmain-action = load-file 40 move "filemgr" to ds-set-name 41 move ds-push-set to ds-control 42 move 1 to ds-control-param 43 initialize filemgr-data-block 44 move filemgr-data-block-version-no to 45 ds-data-block-version-no 46 move filemgr-version-no to ds-version-no 47 call "dsgrun" using ds-control-block, 48 filemgr-data-block 49 perform file-mgr-work 50 51 when pushmain-action = load-print 52 move "printmgr" to ds-set-name 53 move ds-push-set to ds-control 54 move 1 to ds-control-param 55 initialize printmgr-data-block 56 move printmgr-data-block-version-no to 57 ds-data-block-version-no 58 move printmgr-version-no to ds-version-no 59 call "dsgrun" using ds-control-block, 60 printmgr-data-block 61 perform print-mgr-work 62 when pushmain-action = exit-program 63 move 1 to end-of-actions-flag 64 end-evaluate. 65 66 file-mgr-work. 67 move ds-quit-set to ds-control 68 call "dsgrun" using ds-control-block, 69 filemgr-data-block 70 71 move ds-continue to ds-control 72 call "dsgrun" using ds-control-block, 73 pushmain-data-block. 74 75 print-mgr-work. 76 move ds-quit-set to ds-control 77 call "dsgrun" using ds-control-block, 78 printmgr-data-block 79 move ds-continue to ds-control 80 call "dsgrun" using ds-control-block, 81 pushmain-data-block.
The function of this code is detailed as follows:
1 $SET ANS85 MF 2 3 working-storage section. 4 copy "ds-cntrl.mf ". 5 copy "pushmain.cpb ". 6 copy "filemgr.cpb ". 7 copy "printmgr.cpb ".
The first section of the program copies the appropriate Control Block copyfile, and the generated copyfiles for each screenset that will be used.
9 01 new-screenset-name pic x(12).
Next, the picture string for new-screenset-name
is
defined.
11 01 action pic 9. 12 78 load-file value 1. 13 78 load-print value 2. 14 78 exit-program value 3. 15 01 end-of-actions-flag pic 9. 16 88 end-of-actions value 1.
Then, the values for the actions that will cause a particular screenset to be loaded are declared.
20 main-process. 21 perform program-initialize 22 call "dsgrun" using ds-control-block, 23 pushmain-data-block 24 perform process-actions until end-of-actions 25 stop run.
The first procedure in the program is the main-process
.
This performs the routine program-initialization
, then calls
Dsgrun using ds-control-block
and the Data Block for the
pushmain
screenset. It performs process-actions
until end-of-actions
is received and stop-run
occurs.
27 program-initialize. 28 initialize ds-control-block 29 initialize pushmain-data-block 30 move ds-new-set to ds-control 31 move pushmain-data-block-version-no to 32 ds-data-block-version-no 33 move pushmain-version-no to ds-version-no 34 move "pushmain" to ds-set-name 35 move zero to end-of-actions-flag.
The program-initialize
procedure initializes the Control
and Data Blocks, and moves the appropriate values for the screenset
pushmain
. Note that line 30 places the value N in
ds-control
. This is the value you should use if Dsgrun has
not yet been called and started a screenset.
37 process-actions. 38 evaluate true 39 when pushmain-action = load-file
This section of the program performs evaluations to test whether a new
screenset should be loaded. The main screenset is now loaded and has focus
until the value of pushmain-action
changes. If the value of
pushmain-action
becomes load-file
, the
screenset for the file manager will be loaded.
40 move "filemgr" to ds-set-name 41 move ds-push-set to ds-control
When pushmain-action
is equal to load-file
:
filemgr
, is moved to ds-set-name
ds-push-set
is moved to ds-control
.
Note: ds-push-set
is a level-78 data item in
ds-cntrl.mf
, with a defined value of S.
43 initialize filemgr-data-block 44 move filemgr-data-block-version-no to 45 ds-data-block-version-no 46 move filemgr-version-no to ds-version-no 47 call "dsgrun" using ds-control-block, 48 filemgr-data-block 49 perform file-mgr-work
This section of the program performs initialization of the Control Block and Data Block, and checks version information. It then calls Dsgrun using the file manager screenset.
51 when pushmain-action = load-print 52 move "printmgr" to ds-set-name 53 move ds-push-set to ds-control 54 move 1 to ds-control-param 55 initialize printmgr-data-block 56 move printmgr-data-block-version-no to 57 ds-data-block-version-no 58 move printmgr-version-no to ds-version-no 59 call "dsgrun" using ds-control-block, 60 printmgr-data-block 61 perform print-mgr-work
This section performs the identical functions for the print manager
screenset if pushmain-action
becomes 2.
62 when pushmain-action = exit-program 63 move 1 to end-of-actions-flag
When pushmain-action
is equal to exit-program
,
the value 1 is moved to the end-of-actions-flag
, which
terminates the program.
66 file-mgr-work. 67 move ds-quit-set to ds-control 68 call "dsgrun" using ds-control-block, 69 filemgr-data-block
File management functions are performed by Dialog System and not the
calling program. When they are completed, the active screenset is closed
and the new screenset is popped off the stack. This is performed by moving
ds-quit-set
to ds-control
. When Dsgrun is
called it will use ds-control-block
but ignore filemgr-data-block
.
71 move ds-continue to ds-control 72 call "dsgrun" using ds-control-block, 73 pushmain-data-block.
The program then moves ds-continue
to ds-control
causing the screenset pushmain
to be popped from the
screenset stack. Processing is continued from where it left off.
75 print-mgr-work. 76 move ds-quit-set to ds-control 77 call "dsgrun" using ds-control-block, 78 printmgr-data-block 79 move ds-continue to ds-control 80 call "dsgrun" using ds-control-block, 81 pushmain-data-block.
The same operation is repeated for the print management functions.
custom1.cbl demonstrates the use of multiple instances of the same screenset. Because it is a long program, only those sections relevant to the use of multiple instances are shown. The COBOL programs, screensets, and associated files are included on your samples disk.
The program uses a main screenset called Custom1 and multiple instances of a second screenset called Custom2, which is mapped onto the items in a data group.
45 78 main-ss-name value "custom1". 46 78 instance-ss-name value "custom2".
Sets up the picture strings for the main screenset name and the instance screenset name in the Working-Storage Section of your program.
48 copy "ds-cntrl.mf ". 49 copy "custom1.cpb ". 50 copy "custom2.cpb ". 51 copy "dssysinf.cpy ".
Copies the various copyfiles into the program working storage area. Note that dssysinf.cpy is copied. This copyfile is always required if you are using multiple instances.
53 01 instance-table value all x"00". 54 03 group-record-no pic 9(2) comp-x occurs 32. 55 01 group-index pic 9(2) comp-x value 0.
Sets up an instance table to map the data group onto the screenset fields.
57 78 refresh-text-and-data-proc value "p255". 58 78 dialog-system value "dsgrun". 59 60 77 array-ind pic 9(4) comp. 61 77 display-error-no pic 9(4).
Declares various values. The dialog procedure p255
is used
to refresh the text and data.
63 01 main-screenset-id pic x(8). 64 01 instance-screenset-id pic x(8).
Defines picture strings for the main-screenset-id
and
instance-screenset-id
.
66 01 temp-word pic 9(4) comp-x.
The temp-word
picture string is used to hold the value
indicating the active Data Block. In effect it is a function code. This is
applied later in the program where the value of temp-word
can be evaluated and the appropriate action performed.
103 move data-block-ptr(1:2) to temp-word(1:2)
A problem when multiple screensets are used is to know which screenset
Data Block is active. This code moves the first two bytes of the Data
Block into temp-word
where it is used as a function code.
104 evaluate temp-word 105 106 when 1 107 perform set-up-for-ss-change 108 move x"0000" to data-block-ptr(1:2) 109 110 when 2 111 perform poss-invoke-new-instance 112 move x"0000" to data-block-ptr(1:2) 113 114 when 3 115 perform close-instance 116 move x"0000" to data-block-ptr(1:2) 117 118 when 4 119 perform update-details 120 move x"0000" to data-block-ptr(1:2) 121 122 when 5 123 perform close-all-instances 124 move x"0000" to data-block-ptr(1:2) ... 141 end-evaluate 142 perform clear-flags 143 perform call-dialog-system.
Evaluates the value of temp-word
and performs the
appropriate action. When the evaluation finishes, all flags are cleared
and Dialog System is called.
271 call-dialog-system section. 272 273 call dialog-system using ds-control-block, 274 data-block-ptr 275 ds-event-block 276 if (ignore-error = 0) 277 if not ds-no-error 278 move ds-error-code to display-error-no 279 move ds-error-details-1 to display-error-details1 280 move ds-error-details-2 to display-error-details2 281 display "ds error no: display-error-no 282 ", " display-error-details1 283 ", " display-error-details2 284 "Screenset is " ds-set-name 285 end-if 286 end-if 287 .
Calls Dialog System using ds-control-block
, data-block-ptr
(the pointer to the particular screenset instance Data Block), and ds-event-block
.
If Dialog System cannot be called, it displays an error.
294 set-up-for-ss-change section. 295 move ds-event-screenset-id to ds-set-name 296 move ds-use-instance-set to ds-control 297 move ds-event-screenset-instance-no to 298 ds-screenset-instance
Moves the parameters to Dsgrun to cause a change to a new screenset as a
result of an OTHER-SCREENSET event. You could check whether you want to go
to the first screenset then move ds-use-set
instead of
ds-use-instance-set
. The first screenset instance number is
still returned, even though there is only one on the stack.
319 poss-invoke-new-instance section. 320 321 set not-found to true 322 move 0 to group-index 323 perform until found or group-index = 10 324 325 add 1 to group-index 326 if group-record-no(group-index) = 327 customer-index-of-interest 328 set found to true 329 end-if
Checks to see if the required group-occurrence has already been instantiated.
331 if found 332 move ds-use-instance-set to ds-control 333 move instance-screenset-id to ds-set-name 334 move group-index to ds-screenset-instance 335 move group-record-no(ds-screenset-instance) 336 to group-index 337 338 move "show-yourself" to ds-procedure 339 move customer-group-001-item(group-index) to 340 redef-block 341 set address of data-block-ptr to address of data-block
If the group occurrence has been found, brings it into focus.
344 move ds-push-set to ds-control 345 move instance-ss-name to ds-set-name 346 move data-block-version-no to ds-data-block-version-no 347 move version-no to ds-version-no 348 move ds-screen-noclear to ds-control-param
If the group occurrence is not found, creates a new screenset occurrence.
353 move 1 to ds-clear-dialog 354 move "init-proc" to s-procedure 355 356 move customer-index-of-interest to group-index 357 move customer-group-001-item(group-index) to 358 redef-block 359 set address of data-block-ptr to address of data-block 360 361 perform call-dialog-system
Moves the procedure init-proc
to ds-procedure
to show the first window. When control is returned, sets the address of
the Data Block pointer.
365 move ds-screenset-id to instance-screenset-id 366 move group-index to 367 group-record-no(ds-screenset-instance) 368 end-if 369 .
Stores the screenset-id and the line of the group this screenset instance is dealing with.
370 close-instance section. 371 372 move ds-quit-set to ds-control 373 move 0 to group-record-no(ds-screenset-instance) 374 .
Closes a particular screenset instance.
377 update-details section. ... 382 move group-record-no(ds-screenset-instance) to 383 group-index 384 move group-index to customer-index-of-interest 385 move redef-block to customer-group-001-item(group-index) ... 389 move 0 to group-record-no(ds-screenset-instance)
Copies the information from the screenset instance to the main screenset
and sets customer-index-of-interest
to enable the screenset
to update the correct group occurrence. It then clears the value of the
instance table by moving 0 to the group-record-no
.
394 perform derivations 395 move ds-use-set to ds-control 396 move main-screenset-id to ds-set-name 397 move "refresh-proc" to ds-procedure 398 399 set address of data-block-ptr to 400 address of customer-data-block 401 .
Reinstates the main screenset and causes a refresh of the list box.
404 close-all-instances section. ... 408 move 0 to group-index 409 move 1 to ignore-error 410 perform 10 times 411 412 add 1 to group-index 413 if group-record-no(group-index) not = 0 414 move instance-screenset-id to ds-set-name 415 move group-index to ds-screenset-instance 416 move ds-use-instance-set to ds-control 417 move "terminate-proc" to ds-procedure 418 perform call-dialog-system 419 move 0 to group-record-no(group-index) 420 end-if 421 422 end-perform
Closes all active screenset instances.
427 set address of data-block-ptr to 428 address of customer-data-block
After closing all active screenset instances, reinstates the main screenset and sets the Data Block pointer.
Copyright © 2000 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names
used herein are protected by international law.
Questions and Answers | Tutorial - Creating a Sample Screenset |