PreviousProgramming Your Own Controls Migrating to Different PlatformsNext

Chapter 11: Multiple Screensets

This chapter shows you how to use multiple programs and screensets using Dialog System. It covers both Dsrunner and using the call interface to maintain multiple screensets in your application.

When using multiple screensets, you can call Dialog System in two ways:

11.1 Dsrunner

Most applications should be able to use Dsrunner. This is the simplest way of calling Dialog System. It enables you to develop a modular Dialog System application with multiple screensets and multiple sub-program modules. You can therefore focus on your business logic and supporting screenset, without needing to worry about the details of calling Dialog System.

The Dsrunner program loads the Dsrunner screenset which is a template for a main window that enables you to launch other screensets. It handles any subprogram and screenset switching as required. This means that you do not have to supply any code to switch between multiple screensets or multiple subprograms.

11.1.1 Dsrunner Architecture

Dsrunner is a program which runs your application as a subprogram. This means you use Dsrunner to launch a screenset which involves loading the screenset and calling its associated subprogram.You can launch further screensets from that screenset, providing that you have set up your Data Block correctly.

If you want to use multiple screensets and multiple programs, you need to implement a method of program and screenset switching that ensures that the correct screenset and program are loaded when an event occurs. A sample program, called Router, is provided with Dialog System to demonstrate this and is described later in this chapter.

Dsrunner does all the work that Router does and more.

11.1.2 Dsrunner Operation

Dsrunner is the main program in an application. The application typically also contains other screensets and sub-programs. The main (Dsrunner) screenset provides the first windows in the application and the Dsrunner program provides functions that load other screensets and subprograms.

Each screenset (optionally) has a subprogram associated with it. The association of a screenset with a subprogram is made by using the same name (except for the file extension) for them both. For example, if a screenset is named, its associated subprogram should be named dsrnr.cbl.

When a screenset and its associated subprogram are launched:

  1. Dsrunner allocates some memory for the Data Block for the screenset and initializes it to LOW-VALUES.

  2. The subprogram is called before the screenset is loaded into Dialog System.

    This allows any initialization to be performed.

  3. The subprogram executes an EXIT PROGRAM when it finishes its initialization.

  4. The EXIT PROGRAM causes Dsrunner to load the screenset.

  5. The screenset executes any SCREENSET-INITIALIZED logic present then enters the event processing loop.

    If a screenset executes a RETC instruction, it returns to Dsrunner.

  6. Dsrunner then checks to see whether a Dsrunner function is requested (by checking if a valid SIGNATURE and function code are specified).

  7. The sub-program:

    1. Performs any requested function.

    2. Updates the Data block.

    3. Executes an EXIT PROGRAM which returns control to Dsrunner.

    Dsrunner returns control to the screenset. Parameters

When the sub-program is called, it is passed four parameters which must appear in the Linkage Section of the program. They must not appear in the Working-Storage Section of the program because they are parameters for a subprogram.

The parameters are: Dsrunner Screensets

Dsrunner can run any screenset without any special actions on your part, providing the screenset-id is defined in the Configuration, Screenset choice on the Options menu. The screenset-id is required so that Dsrunner can switch between screensets.

The Dsrunner screenset supplied with Dialog System, is in the DialogSystem\bin subdirectory. This screenset is a template that you can modify. Alternatively you can write your own screenset, but you must make sure that you set up the Data Block correctly and have the required global dialog.

Data Block Header

A Dsrunner screenset must contain the following fields at the start of the Data Block. These fields hold controlling and dispatching information and are:


If the main screenset does not follow these rules it can still be started. However, no other applications can be launched.

If you want to use a shared memory buffer, the following fields must be inserted immediately after the DSRUNNER-DATA-ITEMS group:

  YOUR-DATA               any format or size

You also need to reserve some fields for Dsrunner's use at the start of the Data Block. For this you can import the file dsrunner.imp at the start of the Data Block of the screenset. This import file also contains the key statements required in your global dialog to:

Dsrunner Screenset Requirements

You must ensure that each screenset to be used with Dsrunner:

Dsrunner Global Dialog

This dialog describes the key parts of the global dialog in the supplied Dsrunner screenset:


This dialog causes an event that occurs for an inactive screenset to be repeated (stacked for the inactive screenset). The RETC causes Dsrunner to switch the active screenset to the correct screenset. This is required if you want to control more than one screenset.


This dialog sets up the signature indicating that the Data Block of this screenset is set up for Dsrunner. If you do not set up the Data Block, Dsrunner ignores any function codes and a RETC invokes only the subprogram associated with the screenset.


On a request to close the application, the SET-EXIT-FLAG is issued. This causes Dsrunner to terminate after the RETC. If you want to perform termination processing in your subprogram, set your own termination flag and do a RETC before you set the exit flag and do the RETC to Dsrunner.

* resulting file name is left in param-string

This dialog shows how to perform a Dsrunner function. In this example, the file requester is shown and a file name obtained. The function to launch a screenset is then executed.

11.1.3 Dsrunner Program and Functions

The Dsrunner program provides certain functions through the first few fields of its Data Block. These include:

For a list of all of the available functions, see the topic Dsrunner Functions in the Help.

11.1.4 Using Dsrunner Functions

Because Dialog System is called by Dsrunner, you set the Dsrunner function code in the Dsrunner Data Block before executing a RETC from the Dsrunner screenset. For example:

  MOVE "screenset-name" DSRUNNER-PARAM-STRING(1)

In this example, screenset-name is the name of the screenset to launch. The function returns the screenset instance, which is saved as SAVED-SS-INSTANCE.

11.1.5 Starting Screensets Using a Command Line

Dsrunner is designed to be run from a command line:

runw dsrunner [screenset-name /l /d screenset-name]


screenset-name is the name of the initial screenset to load. You can enter it in the first positional parameter, or following the /l "load screenset" parameter. You can also specify the /d switch.

/d enables the Screenset Animator immediately, so the Screenset Animator is invoked when the first line of dialog in the first screenset is executed.

Dsrunner is provided in both .obj and .gnt formats to enable you to package your application appropriately for the run-time environment you are using.

11.1.6 Starting Screensets in NetExpress IDE

Screensets can also be started via Dsrunner in the NetExpress IDE:

  1. Select Settings on the Animate menu.

  2. Specify dsrunner in Start animating at.

  3. Specify the options listed above (/l, /d) in Command line parameters.

Any program breakpoints you have will stop execution and load the relevant program into a debug/edit window.

11.1.7 Starting a Screenset from a Program

Instead of using a command line, you can call Dsrunner from a program. This enables you to choose your own name for your application and to specify the initial screenset name, without specifying it on the command line. This is useful if your application takes its own command line arguments. It is also useful to perform any application-specific initialization, for example opening a library.

11.1.8 Launching a Screenset

To launch a screenset:

  1. Select Open on the File menu in the Dsrunner window.

  2. Select a screenset and click OK.

    The screenset you select is loaded and the associated program run.

You can select another screenset and run that by repeating the above instructions.

11.1.9 Launching an Application

In this section we look at the Dsrunner architecture and consider what you need to do to be able to use Dsrunner effectively. You can modify the Dsrunner screenset to meet your own requirements. The supplied screenset is only an example. You can change the Data Block, but do not make changes that affect dsrunner-info-block.

When you launch a screenset, Dsrunner goes through the following procedure:

  1. When you select Open on the File menu in the Dsrunner window, you are prompted to enter a screenset name.

  2. Dsrunner checks that the screenset is correct, that is, that you have specified a screenset-id. If the screenset is:

  3. The program with the same root file name (and path) as the screenset name is called.

    This program can be any valid COBOL executable in the current directory or $COBDIR (normal COBOL program search rules apply). If the program is not found, a message box is shown with appropriate text.

  4. A call is made to the subprogram to enable the subprogram to perform any initialization required, including the initialization of the Data Block.

    The following parameters are passed:

  5. Once the subprogram is initialized, it must return to Dsrunner with a return code of zero:

  6. Whenever the screenset executes a RETC, the subprogram will be called.

  7. To close down the application, the screenset must SET-EXIT-FLAG in the dialog. Running the Sample Subprogram

Dsrnr is a sample subprogram supplied with Dialog System. To find out how to launch it and for details of key sections of the sample code, see the chapter Sample Programs.

11.2 Multiple Screensets and the Router Program

The Dialog System run-time system can be programmed to enable the use of:

Using these features you can:

When you design your screenset and calling program, you should consider in detail how you control screenset handling, looking at issues such as:

For more information on the basics of screen control using the Dialog System call interface, see the topic The Call Interface in the Help.

11.2.1 Using Multiple Screensets

You can use multiple screensets by pushing and popping them from the screenset stack. By definition, this is a first in, last out operation. Pushing and popping screensets is useful to:

There are no pre-conditions for pushing a screenset onto the screenset stack, and any screenset, or occurrence of a screenset, can be pushed or popped. Pushed screensets are normally stacked in memory, but if memory is short they will be paged to disk.

11.2.2 Using Multiple Programs and Screensets

The recommended way of developing a large application is to build a separate module for each component and associate each module with its own screenset. Each component is then a separate COBOL program complete with its own user interface.

For example, if you were building an application that has a main data entry component and two utility components, one utility would handle all the printing functions and the other handle the file management functions.

Several screensets can be used in the same application, each being placed on the screenset stack. This stack is similar in concept to the call stack that is used whenever you call a program. Calling screensets in turn is easy, because you simply make the call to Dialog System with a value of N in ds-control and with the new screenset name in ds-set-name. By default, the old set is cleared from the screen before a new one is started.

Once you have multiple programs, each with an associated screenset, you need a method to ensure that the correct program and the correct screenset are made active when an event occurs. The sample program that follows, Router, shows you how to structure an application to have multiple programs, each with an associated screenset.

11.2.3 Terms and Concepts

Before you look at the Router program, you need to understand a few terms and concepts. The Active Screenset

When several screensets are loaded, we need to distinguish between the active screenset and inactive screensets. Graphical objects displayed by screensets that are presently inactive do not differ in appearance from those displayed by the active screenset. The active screenset is the one that is currently receiving events. Only one screenset can receive events at a particular instant.

When using multiple screensets, you usually specify the active screenset by calling Dialog System and specifying ds-use-set in ds-control. The screenset specified in ds-set-name becomes the active screenset. This call is very fast and any overhead resulting from this swapping is minimal. Events for Other Screensets

If an event occurs for a screenset other than the one that is currently active, a special event, the OTHER-SCREENSET event, occurs in the current screenset. This event simply tells the current screenset that an event has occurred that should be posted to another screenset. Any resulting action depends on the logic in the active screenset.

If the OTHER-SCREENSET event is not found (usually in global dialog), nothing happens. You must specify the OTHER-SCREENSET event so a screenset can detect that an event has occurred for another screenset. Once such an event is detected, you can then make the appropriate screenset active. The most common way is to set a flag indicating that the OTHER-SCREENSET event has occurred and return to the calling program to change screensets.

All events that occur for inactive screensets are returned to the active screenset as OTHER-SCREENSET events.

You can identify the correct screenset by calling Dialog System and specifying the ds-event-block. When Dialog System returns to the calling program, the screenset-id of the screenset that the event was really for is in ds-event-screenset-id. This screenset-id is specified in Configuration, Screenset on the Options menu. It is not mandatory to specify a screenset-id, but if you do not, you cannot use multiple screensets because you cannot differentiate between the screensets on the stack.

When the correct screenset is active, the original event is repeated providing that you have specified the REPEAT-EVENT dialog function within the OTHER-SCREENSET event.

Note: The repeated event is not OTHER-SCREENSET: it is the event that would have occurred if the correct screenset had been active.

11.2.4 Multiple Screenset Sample Application Using Router

A sample application illustrating how to use Router to handle multiple screensets in Dialog System is included in your sample directory. In this example, Programa, the main program, calls subprograms Programb and Programc. Each program has its own screenset.

A fourth program, Router, handles the routing function. Its only purpose is to determine which program (and screenset) needs to be executed next and then call that program.

Figure 11-1 shows the application structure.

Router structure
Figure 11-1: Structure of Router Application

11.2.5 Using Multiple Instances of Screensets

As well as using multiple screensets, you can use multiple instances of the same screenset. You use multiple instances in a very similar way to using multiple screensets. The real difference is in identifying the screenset. See the section Using Multiple Programs and Screensets before you read this section.

Possible uses of multiple instances of screensets are:

Using multiple instances of the same screenset requires your program to:

When multiple instances are used, a screenset is first started by an "N" or "S" call.

To create a new instance:

  1. Push a new screenset onto the stack by calling Dialog System.

  2. Specify ds-push-set in ds-control.

  3. When Dialog System returns, it places an allocated instance value in the ds-screenset-instance Control Block field.

    An instance value is always returned, but you only need to use it when you use multiple instances of a screenset.

The instance value is unique to that particular screenset instance. Your application must keep track of instance values because they are not assigned in any particular order. Tracking the Active Instance Value

You can track the active instance by examining ds-event-screenset-id and ds-event-screenset-instance-no within dssysinf.cpy, which must be copied into your program Working-Storage Section. For more information on dssysinf.cpy, see the chapter Using Panels V2.

To specify that you want a new instance of a screenset to be loaded:

To identify the appropriate instance for a particular event:

To call Dialog System with a particular instance value:

  1. Move ds-event-screenset-instance-no into ds-instance.

  2. Specify the required screenset name by moving ds-event-screenset-id into ds-set-name.

  3. Call Dialog System.

Notes: Using the Correct Data Block

If you are using multiple instances of a screenset, you must maintain multiple copies of the Data Block. You can do this in several ways:

For more information see the topic Screenset Animator in the Help. Sample Programs for Multiple Instances

There are two sample programs which demonstrate the use of the call interface by your program:

You can find key sections of code for these programs in the chapter Sample Programs.

11.2.6 The Router Program

Before we look at the Router program logic, let's take a look at the copyfile that represents a data area shared by Router and all the programs that are called by Router.

The following code shows the copyfile router.cpy, which contains a program name and two flags.

program-name contains the name of the program to be called next.

cancel-on-return is set to TRUE by a program which is to be cancelled when it returns to Router. If the main program (Programa) requests cancel, Router sets exit-on-return, then exits the main perform loop.

  1 01  program-control.
  3     03  dispatch-flag          pic 9(2) comp-5.
  4         88 cancel-on-return    value 1 false 0.
  6     03  exit-flag              pic 9(2) comp-5.
  7         88 exit-on-return      value 1 false 0.
  9     03  program-name           pic X(8).

Router starts by calling the main program Programa. When Programa determines that a sub-program is required to handle a particular function, it puts the name of the sub-program in program-name and exits. Router then calls the program in program-name.

 29 main-section.
 31*    Make sure we don't exit straight away
 32     initialize exit-flag
 34*    Start by calling the main program
 35     move main-program to program-name
 37*    Call program in program-name until exit is requested
 38     perform until exit-on-return
 40*      Remember who we've called
 41       move program-name to dispatched-program
 43*      Dispatch program in Program-Name
 44       call program-name using
 45       if cancel-on-return
 46*        If last program requested cancel - do cancel
 47         set cancel-on-return to false
 48         cancel dispatched-program
 49         if dispatched-program not = main-program
 50*          Re-load main program if sub-program cancelled
 51           move main-program to program-name
 52         else
 53*          If main program requested cancel, request exit
 54           set exit-on-return to true
 55         end-if
 56       end-if
 57     end-perform
 59     stop run.

If you want to cancel a program, the program must set cancel-on-return before it returns to Router. If the program specified in main-program requests cancel, Router exits after cancelling the main program.

11.2.7 The Main Program

This section shows the source for the main program that the Router calls, Programa. The two subprograms Programb and Programc are very similar.

Lines 31-44:
 31 procedure division using program-control.
 33 main-section.
 34     if new-instance
 35*    First time in we push a new screenset onto the stack
 36          perform new-set-instance
 37     else
 38*    Once we've initialized use existing screenset
 39          perform use-set-instance
 40     end-if
 41*    Call Dialog System as long as we should be active
 42     perform until program-name not = this-program-name
 43          perform call-ds
 44     exit-program.

The main section of Programa checks whether the screenset instance has been created. If it has, the program uses it; if it hasn't, the program creates it.

Once an instance exists, Dialog System is called to display it. Dialog System is called until the name of the program in program-name is changed from Programa.

Programa exits (and returns to Router) if program-name is not Programa. Router, in turn, calls the program in program-name.

Lines 46-60:
 46 new-set-instance
 47 ...
 58 ...
 59*    Push a new screenset onto the stack
 60     move ds-push-set to ds-control.

The most important part of new-set-instance is specifying ds-push-set so that when Dialog System is called. it places the screenset on the stack.

Lines 62-66:
 62 use-set-instance.
 63*    Use existing screenset on the stack
 64     move ds-use-set to ds-control
 65*    This is what we're called
 66     move this-program-name to ds-set-name.

When the screenset instance has been created, we can use it by telling Dialog System the screenset name and directing Dialog System to use that screenset from the stack.

Lines 67-101:
 67 ...
 68 call-ds.
 69*    Standard initialization and call
 70     initialize programa-flags
 71     call "dsgrun" using ds-control-block
 72                        programa-data-block
 73                        ds-event-block
 74     evaluate true
 75*    When this Screenset flag is set we tell router to exit
 76          when programa-terminate-true
 77              set exit-on-return to true
 78 ...
 87 ...
 88          when programa-other-set-true
 89              move ds-event-screenset-id to program-name
 90*    If the Programb menu item is selected, this flag is set
 91          when programa-program-b-true
 92*             So we then request Programb to be dispatched
 93              move "programb" to program-name
 94*    If the Programc menu item is selected, this flag is set
 95          when programa-program-c-true
 96*             So we then request Programc to be dispatched
 97              move "programc" to program-name
 98*    Its an event for us
 99          when other
100              move "Hello A" to programa-field1
101     end-evaluate.

This code fragment shows a standard call to Dialog System specifying all three parameters, followed by an evaluation. This evaluation directs the overall operation of the program, based on flags set in screenset dialog.

Depending on the flags set in the screenset dialog, Programa exits, switches screenset and program, calls a subprogram, or handles an event for it.

The crucial element of this code is the switching of programs and screensets when the OTHER-SET-TRUE flag is set. Dialog System places the Screenset-ID (set using Configuration, Screenset on the Options menu) of the screenset for which the event occurred in ds-event-screenset-id.

This means that Programa can detect the correct screenset-id and hence program name because this example, conveniently, calls the screenset and its associated program by the same filename. If the screenset and its associated program name differed, you would need to identify the screenset then call the appropriate program.

Programa puts the screenset-id into ds-screenset-name and exits; Router will call the identified program and hence load the correct screenset.

11.2.8 Multiple Screenset Dialog

The following example dialog shows screenset dialog needed to handle multiple screensets. The dialog listed here is taken from the Programa screenset, but it is the same for the other screensets.

Dialog System uses the OTHER-SCREENSET event to detect that an event has occurred in a screenset other than the one that is currently loaded. In this example, this event is located in the global dialog table for each screenset:


When such an event is detected, the flag OTHER-SET is set, to signal to the program that another screenset is to be used.

Next, the REPEAT-EVENT function is executed. REPEAT-EVENT tells Dialog System to repeat the last event the next time it goes for input. This occurs when the next screenset is loaded and control is in the next program. After the REPEAT-EVENT, the screenset returns to the calling program using RETC .

The calling program, in this case Programa, can then check the screenset flag. If the flag is set, the program can place the screenset-id in ds-set-name (assuming the screenset name and program name are the same) and exit to Router. Router then calls the appropriate program and hence loads the correct screenset. Then, because of the REPEAT-EVENT function issued by the Programa screenset, the event that caused the OTHER-SCREENSET event is repeated.

Note: The event repeated is not OTHER-SCREENSET; it is the event that would have occurred if the correct screenset had been active.

For more information on these functions, refer to the topic Dialog Statements: Functions in the Help.

11.2.9 The Sequence of Events

The previous sections have described the overall process of switching screensets and the key events that occur. However, if you trace the program flow, all is not quite so simple in practice. There are, in fact, several program switches before control is left in the appropriate program.

Why? The key reason is the change of focus. When the input focus moves from one graphical object to another, two events occur. The object losing focus receives the LOST-FOCUS event, and the object gaining focus receives the GAINED-FOCUS event.

If the object that loses focus is a control object, the LOST-FOCUS event also occurs for the window that contains that object. Similarly, if the object that gains focus is a control object, the GAINED-FOCUS event also occurs for the window that contains the object.

This table shows the sequence of events that actually occurs when there is a simple change of focus from A's window to B's window.

System Event Active Screenset Event Screenset DS Event
Mouse-button-1-down A B OTHER-SCREENSET
Lost-focus (window A) B A OTHER-SCREENSET
Gained-focus (window B) A B OTHER-SCREENSET
Mouse-button-1-up B B ANY-OTHER-EVENT

Each screenset traps the OTHER-SCREENSET event and returns to the calling program from Dialog System. Dialog System is then called with the correct screenset (identified from ds-event-screenset-id).

Pressing the mouse button on B's window when A has the focus causes the sequence of events shown in this table.

The system event Mouse-button-1-down on window B causes Dialog System to present an OTHER-SCREENSET event to the active screenset. This gives program A a chance to switch to screenset B.

However, the next system event is window B losing focus. But, as you can see in the table, this event occurs only after the switch to B. This in turn causes an OTHER-SCREENSET event in B.

Another switch of screensets results. B now gains focus when A is active, so another OTHER-SCREENSET event results. This causes B to become active. The mouse button up event is now presented to B as ANY-OTHER-EVENT (because all mouse events are translated to this event).

This sequence of events need not trouble you once you understand the principle of screenset swapping because no matter how many screenset swaps take place, the correct screenset is left active once a steady state is reached.

Note: In this example, the mouse button down event is lost. You can rectify this using the REPEAT-EVENT function within the OTHER-SCREENSET dialog. Repeating the Event

First, you must decide whether you need to repeat the event. The purpose of repeating the event is clear. If you need the event, it must be repeated in the correct screenset. However, in many cases, you do not need the event, therefore you do not need to repeat it.

The event sequence caused by clicking buttonB on windowB when focus is currently on buttonA on windowA is the following:

Lost-Focus on buttonA
Lost-Focus on windowA
Gained-Focus on windowB
Gained-Focus on buttonB
Button-Clicked on buttonB

This sequence shows that you do not need REPEAT-EVENT in this situation, because the Gained-Focus on windowB loads ScreensetB before the Button-Clicked event causes a BUTTON-SELECTED event.

11.2.10 Setting the Focus

When a screenset is made active by calling Dialog System and specifying ds-use-set in ds-control, it does not automatically receive the focus. If the screenset switch is caused by the user (by selecting a new window or control), the focus moves to the new screenset because the user's actions cause a GAINED-FOCUS event.

If the switch is caused by the program, you must specify a dialog procedure name in ds-procedure before you call Dialog System. Use a SET-FOCUS dialog function to set the focus on the appropriate window.

11.3 Further Information

For a detailed description of the call interface see the topic The Call Interface in the Help, which provides information on the Control Block, including the Event Block, the Data Block, use of the Screenset Animator, version checking, and values the calling program returns to Dialog System.

Copyright © 1998 Micro Focus Limited. All rights reserved.
This document and the proprietary marks and names used herein are protected by international law.
PreviousProgramming Your Own Controls Migrating to Different PlatformsNext