Presentation Manager Applications (16-bit) | Microsoft Windows Applications |
This chapter explains how to create OS/2 Presentation Manager applications using the 32-bit COBOL system for OS/2 V2. It assumes you have a basic knowledge of the concepts involved in writing a Presentation Manager program.
This chapter assumes you are using the 32-bit Presentation Manager API available with OS/2 V2 and later. For details on the 16-bit Presentation Manager API see the chapter Presentation Manager Applications (16-bit).
Presentation Manager (PM) is a graphical user interface (GUI) for OS/2 which provides functions for creating windowed applications. Presentation Manager implements the Common User Access (CUA) user interface standard, allowing you to create applications with a common style of interface.
Micro Focus offers three approaches to 32-bit Presentation Manager programming in COBOL:
The chapter Comparison of Methods for Creating User Interfaces explains the advantages and disadvantages of each approach. The remainder of this chapter describes how to create applications that use the Presentation Manager API.
In addition to the 32-bit COBOL system, you need the OS/2 Programmer's Toolkit available from your operating system supplier. This software package includes the Dialog Editor, Icon Editor, and Resource Compiler, as well as the C header files that contain the type information and constants used by the OS/2 API functions.
The Resource Compiler converts menu definitions, icon declarations, accelerator tables, and other structures from readable ASCII files to a binary format which can be incorporated in an .exe or .dll module. The editors enable you to paint dialog boxes, icons and fonts.
Your OS/2 Programmer's Reference describes the OS/2 API functions used by Presentation Manager applications. However, the function descriptions and examples in the OS/2 Programmer's Reference are in C. This chapter explains those descriptions for programmers unfamiliar with C and describes how to translate them into COBOL. This COBOL system includes the H2cpy utility, which allows you to translate #define and typedef information in the C header files into their COBOL equivalents. See the chapter Header-to-COPY Utility in your Programmer's Guide to Writing Programs for details about converting C header files with H2cpy.
This system includes two sample Presentation Manager programs, Pmhello and Pmcalc2. These are used as examples in this chapter.
OS/2 offers Presentation Manager as a graphical user interface to applications in a multitasking environment. An application running under Presentation Manager shares the display with other tasks by using windows, which it creates for interaction with the user. Presentation Manager manages the screen, so an application does not have to worry about other windows on the screen.
In a traditional environment, the program accepts user input in a predetermined order. This is called procedural logic. In a windowed environment, applications respond to user input events as they occur. This is called message-based or event-driven logic. For example, a window event such as a mouse click can occur at any time; the application must respond to that event immediately.
Presentation Manager puts information from the mouse and keyboard in a standard format called a message. These messages are stored in a queue until they are retrieved by the application - there is a separate queue for each application. Each message in the queue contains information identifying the window that received the message, the message event itself (for example "left button pressed" or "Escape key pressed") and any other applicable information.
Such event driven programming is an integral part of Presentation Manager object oriented programming where events are called messages and recipients of messages are called objects. Examples of Presentation Manager objects are windows, dialog boxes and menus.
A Presentation Manager application must create a message queue and implement a message loop. This loop retrieves messages from the message queue and dispatches them to the message handler (called a Window Procedure or WinProc for short) for the window receiving the message.
Each WinProc implements a window class. Many instances of each window class (or type) can be created, but they all share the same WinProc. Window classes are given a name and must be registered with the Presentation Manager subsystem before they can be used.
Extensions have been added to the COBOL syntax to enable the systems programming facilities required to program application programming interfaces like Presentation Manager application programming interface (API). These extensions are grouped under the name Systems Programming Extensions.
The Systems Programming Extensions include:
All of these are described fully in your Language Reference. Examples of their use are given in this chapter.
The OS/2 V2 API uses the system parameter-passing convention. This means that:
This convention is the same as that used by this COBOL system, so you do not need to use the CALL-CONVENTION clause when accessing the OS/2 V2 API.
By default, the parameters passed by a COBOL CALL statement are address references, using the address of the parameters in memory. Presentation Manager requires some parameters to be passed by value. The example below shows how to do this.
Remember to specify the size in bytes using the SIZE clause with numeric literals. If you do not specify the SIZE clause, a size of four is assumed.
Example
call "myprog" using by reference param-1 by value param-2 by value 27 size 2
The mechanisms for returning values from a WinProc, and receiving values returned from an API routine are explained in the following sections.
The RETURNING phrase of a CALL statement stores a value returned by an OS/2 API function.
Example
call "WinInitialize" using by value 0 size 4 returning hab
This stores the result returned by the API function WinInitialize in the
data item hab
. Presentation Manager calls return either a
two byte or four byte value.
A Presentation Manager WinProc often needs to return a value to the function that called it. In COBOL, use the RETURNING phrase on the EXIT PROGRAM statement:
Example
exit program returning mresult
A data item declared as PROCEDURE-POINTER passes the address of a WinProc to Presentation Manager so that it can call that procedure with messages for the window.
Example
03 WndProc usage procedure-pointer. . . . . . . entry "WndProc" using by value hwnd set WndProc to entry "WndProc" call 'WinRegisterClass' using by value hab by reference MyClass by value WndProc by value CSClass by value 0 size 4 returning my-refum-value.
Since a Presentation Manager program can process a new event before the processing of a prior event is complete, recursion is required. That is, a program must be able to call itself. It is important that the processing of data should not hold up the handling of events.
Example
Support for recursion enables you to write a message loop as follows:
perform until loop-end call "WinGetMsg" using ... call "WinDispatchMsg" using ... end-perform
By default, all COBOL variables are global ; that is, any variable defined in the Working-Storage Section can be referenced from any other section of the program.
Since Presentation Manager can call an entry point several times, the local data from one call needs to be protected from another call entering the same code. You can create variables that are local to a particular invocation of a procedure; these variables can be referenced only within that procedure. These variables are created on the stack when a procedure using them is called, then discarded when the procedure terminates. You define these variables in the Local-Storage Section.
Use local variables when writing recursive procedures (see your Programmer's Guide to Writing Programs). If you use global variables in a recursive procedure, each new procedure invocation references the same storage location for a particular variable-name, overwriting information that should be unique to that invocation. The Local-Storage Section eliminates this problem by creating an individual set of procedure variables for each invocation.
Indirect recursion occurs when a procedure invokes Presentation Manager, which in turn calls that procedure. Although it is indirect, this recursion can still overwrite variables that should remain distinct for each invocation. Therefore, unless you are certain that a variable in a Presentation Manager program is truly global and will not change between invocations of a procedure, you should declare it in the Local-Storage Section.
This section of code illustrates the use of the Local-Storage Section:
working-storage section. ... local-storage section. 01 hps pointer. 01 rcl. 03 xleft pic x(4) comp-5. 03 xbottom pic x(4) comp-5. 03 xright pic x(4) comp-5. 03 xtop pic x(4) comp-5. 01 mresult pic x(4) comp-5.
linkage section. 01 hwnd pic x(4) comp-5. 01 msg pic x(4) comp-5. 01 mp1 pic x(4) comp-5. 01 mp2 pic x(4) comp-5. procedure division. main-control section. entry "ClientWndProc" using by value hwnd by value msg by value mp1 by value mp2. ...
All Presentation Manager programs must perform the same basic steps:
The first action in your Presentation Manager application is to call
the WinInitialize function. Calling this function declares that this
program or thread is going to use Presentation Manager. WinInitialize
returns the handle of an anchor block (hab
). The anchor
block handle is a value that identifies the application to Presentation
Manager.
call 'WinInitialize' using by value 0 size 4 returning hab.
In this example, the first parameter passed to the function is an
initialization option and must be set to 0. The returned parameter,
hab
, is the handle to the anchor block for the application.
The next step in your program is to set up a message queue for this
thread. The message queue receives messages sent to all of the windows
which were created by the current program or thread. Your application must
create a message queue before it can create a window. The returned
parameter, hmq
, is the handle to the message queue. This
message queue handle is saved so it can later be passed to the function
that terminates the message queue.
call 'WinCreateMsgQueue' using by value hab by value 0 size 4 returning hmq
Next your program calls WinRegisterClass to create a window class. Every window that is created under Presentation Manager must belong to a window class. The window class defines a WinProc and other information, such as default window styles.
set WndProc to entry 'WndProc' call 'WinRegisterClass' using by value hab by reference MyClass by value WndProc by value CSClass by value 0 size 4 returning bool
After you have created the window class you can create a window. A Presentation Manager window is the main method of interacting with the user.
Your program creates a standard window by calling the WinCreateWindow or the WinCreateStdWindow function:
call 'WinCreateStdWindow' using by value Hwnd-Desktop size 4 by value WSWindow by reference ctldata by reference Myclass by reference 'mytitle' & x'00' by value 0 size 4 by value 0 size 4 by value 0 size 4 by reference hwndClient returning hwndFrame
Presentation Manager sends many messages to each window to convey important information and to inform them of a wide variety of events. To receive these, your application includes a message loop. This loop collects messages from your message queue and dispatches them, via Presentation Manager, to the window specified by the window handle contained in the message.
The function WinGetMsg reads the next available message from the queue. The WinDispatchMsg function dispatches this message throughout the system so the message can be processed.
Example
Processing the message loop:
perform until loop-end call 'WinGetMsg' using by value hab by reference qmsg by value 0 size 4 by value 0 size 4 by value 0 size 4 returning bool if boolfalse set loop-end to true else call 'WinDispatchMsg' using by value hab by reference qmsg end-if end-perform
When your program dispatches a message to Presentation Manager using WinDispatchMsg, Presentation Manager evaluates the message and, if appropriate, sends it to your client window. The link between the window and the WinProc is established by the WinRegisterClass call.
Example
This section of code shows how to process the WM-PAINT message.
entry 'ClientWndProc' using by value hwnd by value msg by value mp1 by value mp2. ... evaluate msg ... when wm-paint call 'WinBeginPaint' using by value hwnd by value 0 size 4 by value 0 size 4 returning hps ... call 'WinEndPaint' using by value hps ... when other call 'WinDefWindowProc' using by value hwnd by value msg by value mp1 by value mp2 returning mresult ... end-evaluate exit program returning mresult.
Before your program exits, it should release the resources it got from Presentation Manager. First you call WinDestroyWindow to close any windows created by WinCreateStdWindow or WinCreateWindow. Then you call WinDestroyMsgQueue to dispose of the message queue created in the WinCreateMsgQueue call. Finally, your program must call WinTerminate to tell the system that you have finished with Presentation Manager.
Example
call 'WinDestroyWindow' using by value hwndFrame call 'WinDestroyMsgQueue using by value hmq call 'WinTerminate' using by value hab
The OS/2 Programmer's Reference describes all the OS/2 API functions in terms of the C programming language. For those programmers unfamiliar with C, this section explains how to translate these descriptions into COBOL.
Your OS/2 Programmer's Toolkit includes definitions of many of the Presentation Manager function parameters in C header (.h) files. This COBOL system includes the H2cpy utility to convert typedef and #define statements in .h files to COBOL copyfile form. H2cpy does not translate function declarations or macro definitions; these have no equivalents in COBOL. See the chapter Header-to-COPY Utility in your Programmer's Guide to Writing Programs for instructions on using H2cpy.
This COBOL system contains a utility, H2cpy, to convert C header files into COBOL copyfiles. The utility converts C header files, including those supplied with the OS/2 Programmer's Toolkit into COBOL data definitions. It is especially useful if you want to write Presentation Manager applications in COBOL using the System Programming Extensions.
H2cpy converts the following C language constructs:
Before you can compile any of the sample programs (or your own Presentation Manager software), you must run H2cpy to translate the C header files into COBOL, using this command line:
h2cpy os2.h os2.cpy /m /dincl_pm /dincl_base
This translates the os2.h file and all its included files into the following files:
H2cpy creates a separate COBOL copyfile (.cpy) for each structure defined in the C files. Use the COPY statement to include these files in your program.
The C definition of the WinCreateStdWindow API function is shown in the following example (the rest of this section explains how to translate this C definition into COBOL):
HWND WinCreateStdWindow (HWND hwndParent, ULONG flStyle, PULONG pflCreateFlags, PSZ pszClientClass, PSZ pszTitle, ULONG styleClient, HMODULE hmod, ULONG idResources, PHWND phwndClient);
The following list defines each of the words in the example:
Word |
Meaning |
---|---|
HWND |
Function returns data of type HWND |
WinCreateStdWindow |
Function-name |
HWND |
The data type of the parameter hwndParent
|
hwndParent |
Possible name for the parameter (optional in the definition, but required in any use of the function) |
ULONG |
The data-type of the parameter flStyle
|
flStyle |
Possible name for the parameter |
. . . | Remaining data types and names |
); |
End of the function definition
|
All OS/2 API function definitions appear in at least one of the OS/2 header files.
You now need to find the definitions of the data types and other constructs and decide how to code them in COBOL. This information is in the files produced by H2cpy.
The first data-type you need to translate in the WinCreateStdWindow example above is HWND. Looking up HWND in the file os2.cpy, you find this definition:
03 HWND pointer.
The C data-type HWND is, therefore, equivalent to the COBOL type, POINTER. Since WinCreateStdWindow returns a value of type HWND, you need to define a storage location for that value, say hwndResult. The procedure should include a line of code to place the return value in this variable:
03 hwndResult pointer.
Next consider the parameters to the function call. The first parameter has type HWND, which has already been defined as a POINTER type. This results in the line:
03 hwndParent pointer.
Next is data-type ULONG. From os2.cpy you get:
03 ULONG pic 9(9) comp-5.
This gives the following definition for flStyle:
03 flStyle pic 9(9) comp-5.
Using the same method for all the parameters, you end up with the following definitions:
03 hwndParent pointer. 03 flStyle pic 9(9) comp-5. 03 pflCreateFlags pointer. 03 pszClientClass pointer. 03 pszTitle pointer. 03 styleClient pic 9(9) comp-5. 03 hmod pic 9(9) comp-5. 03 idResources pic 9(9) comp-5. 03 phwndClient pointer.
Although these definitions are correct, they can be simplified. C normally passes parameters by value, not by reference. Therefore, if the value of the parameter needs to be changed, a pointer to the variable must be passed instead. In COBOL, parameters can also be passed by reference, so a pointer might not be needed. In the above example, some of the pointer definitions can be replaced by the definition of the item pointed to by the pointer. Those items can be passed as parameters by reference.
The standard naming convention used in the C header files uses a type name prefixed by the letter P to indicate a far pointer to that type. For example, PULONG indicates a far pointer to a variable of type ULONG.
Returning to the example above, pflCreateFlags was actually defined as type PULONG. Therefore, you can replace the previous definition with:
03 flCreateFlags pic 9(9) comp-5.
and pass this parameter by reference, which is the same as passing a far pointer to flCreateFlags.
The other parameters that can be replaced are those defined as type PSZ. The PSZ type differs from the standard naming convention used in C header files (described above) in that SZ denotes a null-terminated (C- format) string and type PSZ is a far pointer to a string. Therefore, it can be replaced in the COBOL program with a string of the appropriate length.
COBOL and C strings have different formats. OS/2 expects strings to be null-terminated, so the last character in the string must have the ASCII value of x"00" (null). This is different from COBOL strings, which have a fixed length. Therefore, you must append a byte of x"00" when you pass a COBOL string to an OS/2 API function. For example, you can define the strings as:
03 szClientClass pic x(9) value "MY-CLASS" & x"00". 03 szTitle pic x(9) value "MY-TITLE" & x"00".
Note the use of the & operator to concatenate the string and the x"00" byte to form a null-terminated string.
After you have performed all these conversions, the COBOL call to the API function WinCreateStdWindow becomes:
call 'WinCreateStdWindow' using by value hwndParent by value flStyle by reference flCreateFlags by reference szClientClass by reference szTitle by value styleClient by value hmod by value idResources by reference hwndClient returning hwndResult
If the values you pass to the function are constants, you can use the:
BY VALUE literal
construct as long as you specify the size of the literal. Therefore, if
the values you specify for styleClient
, hmod
,
and idResources
are all 0, you can replace the parameters by
literals, giving the following call:
call 'WinCreateStdWindow' using by value hwndParent by value lStyle by reference flCreateFlags by reference szClientClass by reference szTitle by value 0 size 4 by value 0 size 4 by value 0 size 4 by reference hwndClient returning hwndResult
Constants defined at level-78 do not have any size associated with them. When they are used as parameters in a CALL statement, they default to a size of four bytes. The SIZE phrase of the USING clause can be used specifically to set the number of bytes passed as the parameter.
For example, the constant CS_SIZEREDRAW is defined in the C header files as:
#define CS_SIZEREDRAW 0x00000004L
The L denotes that it is a type LONG. The corresponding level-78 would be defined in os2.78 by H2cpy as:
78 CS-SIZEREDRAW value H"04".
If you use this as a parameter, you would have to add a SIZE 4 clause to specify the correct size.
... by value CS-SIZEREDRAW size 4
Note: C uses the underscore character ( _ ) to split long names or prefixes. The underscore cannot be used in COBOL. Therefore, H2cpy replaces all underscores in names with hyphens (-) .
H2cpy does not convert C macros defined in the header files, because COBOL has no equivalent feature. However, in COBOL, the REDEFINES statement can often be used to achieve the same effect.
Example
The message parameters used by Presentation Manager are defined as type MPARAM. H2cpy produces the following definition for this type:
03 MPARAM pointer.
The message parameters are actually used in different ways, depending on the message being sent. Therefore, C macros are provided in the header files to access parts of the message parameter. To access them in COBOL, you can use the mechanism shown below.
A variable mp1
of type MPARAM would be defined this way:
01 mp1pointer. 01 mp1-9 redefines mp1 pic S9(9) comp-5. 01 redefines mp1. 03 mp1w1 pic S9(4) comp-5. 03 mp1w2 pic S9(4) comp-5. 01 redefines mp1. 03 mp1b1 pic S9(2) comp-5. 03 mp1b2 pic S9(2) comp-5. 03 mp1b3 pic S9(2) comp-5. 03 mp1b4 pic S9(2) comp-5.
The bytes and words of mp1
can now be accessed
individually. The equivalents of the principal C macros are as follows:
C Macro |
COBOL |
---|---|
MPFROMCHAR(x)
|
move 0 to mp1-9
|
The following sections explain how to compile, link and debug your Presentation Manager application.
Compiling a program for Presentation Manager is no different from compiling any other program.
Note that the compiler normally creates a .def file (for use with Animator). If you have already created a .def file for the Presentation Manager .exe file, you should specify one of these directives:
Use the Cbllink utility to compile and link your Presentation Manager COBOL applications. For example, to compile and link Pmcalc2 using Cbllink, use the command:
cbllink -g pmcalc2.cbl
See your Object COBOL User Guide for more details on Cbllink.
When linking Presentation Manager applications with Link386, you must create a .def file with the WINDOWAPI attribute in the NAME statement, or the resulting executable file will not be able to run in a window. The .def file must also include an EXPORTS statement to tell the operating system the starting address of the WinProc. For example, to compile and link Pmcalc2 using Link386, use the commands:
cobol pmcalc2.cbl obj"pmcalc2.obj" litlink; cblnames -v -mpmcalc2 cobintfn link386 /noi/nod pmcalc2,,,mfrts32+mfcmlib+os2386,pmcalc2.def; rc pmcalc2.res pmcalc2.exe
The Presentation Manager definition file, pmcalc2.def, contains these lines:
name pmcalc2 windowapi stacksize 250000 exports mWndProc @1 BWndProc @2 DlgProc @3
If the application includes icons , dialog boxes, or other resources, you must use the Resource Compiler (RC) to add the compiled resource to the linked executable file. The OS/2 Programmer's Toolkit manuals explain how to use the Resource Compiler.
Use Animator V2 in the 32-bit COBOL system to debug Presentation Manager COBOL applications. The environment variable COBANIM_2 must be set to ANIMGUI.
The OS/2 Programmer's Toolkit contains the Resource Compiler and Editor. These utilities, with documentation, are available from your operating system supplier. The Resource Compiler converts items such as menu definitions, icon declarations and accelerator tables from ASCII text to a binary format that can be incorporated in an .exe or .dll module.
The OS/2 Programmer's Toolkit Editor enables you to paint dialog boxes, icons, and fonts.
There are some printer handling routines that are portable between the 32-bit COBOL systems running on OS/2 and Windows. These routines are:
PC_PRINT_FILE | Print a file |
PC_PRINTER_CLOSE | Close a printer channel |
PC_PRINTER_CONTROL | Send a printer command to a printer |
PC_PRINTER_FREE_BMP | Free bitmap from memory |
PC_PRINTER_INFO | Get printer information |
PC_PRINTER_LOAD_BMP | Load bitmap into memory |
PC_PRINTER_OPEN | Open a printer channel |
PC_PRINTER_SET_COLOR | Set printer color |
PC_PRINTER_SET_FONT | Set printer font |
PC_PRINTER_WRITE | Write text to a printer |
PC_PRINTER_WRITE_BMP | Write bitmap to a printer |
These routines are described in the Library Routines chapter of the Programming Guide to Writing Programs.
Two sample programs included with this system provide examples of Presentation Manager programs written in COBOL. The programs are:
Copyright © 1999 MERANT International Limited. All rights reserved.
This document and the proprietary marks and names
used herein are protected by international law.
Presentation Manager Applications (16-bit) | Microsoft Windows Applications |