PreviousQuestions and Answers Tutorial - Creating a Sample ScreensetNext

Chapter 17: Sample Programs

This chapter contains sample dialog for the following objects:

It also contains the following sample programs:

17.1 Entry Fields

Entry fields are described in detail in the chapter Control Objects. This section describes dialog required to:

17.1.1 Validating Entry Fields

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
Line 1:
 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.

Line 2:
     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.

Lines 3-4:
     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.

Line 5:
 VAL-ERROR

The VAL-ERROR event is detected. The special register $EVENT-DATA identifies the entry field that failed validation.

Line 6:
     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.

Line 7:

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.


17.1.1.1 Complex Data Validation

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.

17.1.2 Editing Multiple Line Entry Fields

You can move text to an associated data item using either your application program or dialog.

17.1.2.1 Moving Text Using Your Application Program

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.

17.1.2.2 Moving Text Using Dialog

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.

17.2 Push Buttons

This section covers samples of dialog for:

17.2.1 Dialog for a Pause Push Button

1 BUTTON-SELECTED
2     DISABLE-OBJECT $CONTROL
3     ENABLE-OBJECT CONTINUE-PB
4     BRANCH-TO-PROCEDURE PAUSE-SELECTED
Line 1:
     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.

Line 2:
     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.

Line 3:
     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.

Line 4:
     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.

17.2.2 Dialog for Dynamically Changing Bitmaps Assigned to a Push Button

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     ...
Lines 2-3:
 @SAVE
     BRANCH-TO-PROCEDURE SAVE-FUNCTION

The user selected the Save option from a menu. Branch to the procedure that does the save function.

Line 5:
     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").

Line 6:
     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.

17.3 Check Boxes

Check boxes are described in detail in the chapter Control Objects. The Objects sample program shows an example of using check boxes.

17.3.1 Selecting Items From a List

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.

check boxes

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
Line 1:
 BUTTON-SELECTED

The user selected the Display push button .

Lines 2-5:
     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.

Line 6:
     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.

Line 7:
     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.

Lines 8-9:
     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.

Line 10:
     BRANCH-TO-PROCEDURE CHECK-TOOLSET

Branch to the procedure that checks the Toolset check box.

Lines 12-27:
   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.

Lines 29-31:
   DISPLAY-PRODUCTS-DB
     REFRESH-OBJECT CHECKB-LB
     SET-FOCUS CHECKB-DB

Display the selected products in the list box.

17.4 List Boxes

You can update items in a list box in three ways:

17.4.1 Adding Items Using Group Item

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
Line 1:
    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.

Lines 3-4:
 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.

Line 6:
   PROC-INSERT

This procedure inserts an item in the position now occupied by the selected item.

Line 7:
     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.

Lines 8-10:
     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.

Line 11:
     INCREMENT NUMBER-OF-RECORDS

Increment the number of records in the data group.

Line 12:
     INCREMENT $REGISTER

Update the pointer to the current row. This keeps the pointer addressing the same row it was before the insertion.

Line 13:
     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.

Line 14:
     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.

Line 16:
   PROC-CHANGE

This procedure changes the contents of the selected item.

Lines 17-19:
     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.

Line 20:
     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.

Line 21:
     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.

Line 24:
     DELETE-OCCURRENCE SALES-GROUP $REGISTER

Delete the occurrence from the data group at the selected location. All items following are moved up one row.

Line 25:
     DECREMENT NUMBER-OF-RECORDS        

Decrement the number of records in the data group.

Line 26:
     DECREMENT $REGISTER        

Update the pointer to the current row. This keeps the pointer addressing the same row.

Line 27:
     REFRESH-OBJECT SALES-LB        

Refresh the list box.

Line 28:
     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.

17.4.2 Adding Items Using Dialog

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.

17.4.3 Adding Items Using a Delimited String

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:

MONTHS-STRING X 48

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

17.5 Scroll Bars

This section covers:

17.5.1 Events Associated with a Scroll Bar

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:

Line 1:
     SLIDER-MOVING

The slider is moved to a new position. This triggers the SLIDER-MOVING event.

Line 2:
     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.

Line 3:
     REFRESH-OBJECT COUNTER-DISP

The entry field must be refreshed to reflect the new data value.

Line 4:
     SLIDER-RELEASED

The slider is released at a new position. This triggers the SLIDER-RELEASED event.

Line 5:
     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.

Line 6:
     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.

17.5.2 Scroll Bar Properties

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.

17.6 Tab Controls

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.

Tab control page

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"
Line 1:
 ADD-MORE-SALES-INFO

A procedure to add another sales information page to the tab control.

Line 2:
     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).

Line 3:
     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.

17.7 The Call Interface

Details about using the call interface can be found in the chapter Using the Screenset. This section covers:

17.7.1 Using Dsrnr

Dsrnr is a sample subprogram supplied with Dialog System. To launch it:

  1. Start Dsrunner (see the chapter Multiple Screensets for full details).

    runw dsrunner

  2. Select Open a screenseton the File menu in the Dsrunner window.

  3. Select Dsrnr from the file selector that is displayed (it is in your demonstration directory).

    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.

17.7.2 The Push-pop Sample Program

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:

Lines 1-7:
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.

Line 9:
9  01 new-screenset-name    pic x(12).

Next, the picture string for new-screenset-name is defined.

Lines 11-16:
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.

Lines 20-25:
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.

Lines 27-35:
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.

Lines 37-39:
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.

Lines 40-41:
40   move "filemgr" to ds-set-name
41   move ds-push-set to ds-control

When pushmain-action is equal to load-file:


Note: ds-push-set is a level-78 data item in ds-cntrl.mf, with a defined value of S.


Lines 43-49:
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.

Lines 51-61:
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.

Lines 62-63:
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.

Lines 66-69:
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.

Lines 71-73:
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.

Lines 75-81:
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.

17.7.2.1 The Custom1 Sample Program

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.

Lines 45-46:
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.

Lines 48-51:
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.

Lines 53-54:
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.

Lines 57-61:
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.

Lines 63-64:
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.

Line 66:
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.

Line 103:
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.

Lines 104-143:
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.

Lines 271-287:
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.

Lines 284-297:
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.

Lines 319-329:
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.

Lines 331-341:
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.

Lines 344-348:
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.

Lines 353-361:
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.

Lines 365-369:
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.

Lines 370-376:
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.

Lines 377-389:
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.

Lines 394-401:
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.

Lines 408-422:
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.

Lines 427-428:
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.

PreviousQuestions and Answers Tutorial - Creating a Sample ScreensetNext