Youre probably already using OS/2 REXX for utility applications. By exploiting a freely available IBM add-on function set, you can add a sophisticated GUI interface with little effort. Best of all, no programming prowess is required.
Visual REXX for Presentation Manager, VREXX for short, lets you create and control presentation manager windows and dialogs directly from an OS/2 REXX program. (VREXX requires OS/2 version 2.0 or later.) With VREXX, your REXX program can create windows, put text and graphics in them, and display pop-up dialog boxes to display messages or receive user input. In other words, your program can continue to use the standard REXX features, but the drab command line interface used to say text and pull user input is replaced with contemporary dialog boxes. (Note: VREXX should not be confused with Watcoms commercial product VX-REXX. For more information on VX-REXX, refer to http://www.watcom.on.ca/vxrexx/vxrexx.html.)
In this article, I will introduce you to the VREXX dialog functions. This article will give you the background and confidence youll need to begin exploiting VREXX in your own REXX programs. It will also provide a solid foundation for a future article on VREXXs windowing and drawing functions and how those functions can be used to express data harvested from the AS/400 using REXX EHLLAPI.
Whats Possible with VREXX
VREXX provides a robust suite of GUI functions to enhance your OS/2 REXX programs. They are classified into three categories: dialog functions, windowing functions, and graphics functions. VREXX dialog functions allow a REXX program to display message boxes, list boxes, check boxes, input boxes, and file boxes. This article will explore VREXX dialog functions, which also give you a good introduction to OS/2 PM
concepts. VREXX windowing functions allow a REXX program to create new windows, clear windows, change their foreground/ background colors, resize them, and tear them down.
VREXX graphics functions allow a REXX program to draw complex lines, arcs, splines, polygons, pixels, and text into a window.
VREXX Availability
VREXX is EWS, IBM employee-written software. It is freely available to any OS/2 licensed user and can be downloaded from IBMs EWS ftp site: ftp://software.watson.ibm.com/pub/os2/ews/vrexx2.zip. (The REXX code for the examples used in this article is available at my ftp site: ftp://members.aol.com/cmiksanek/xmpvrexx.zip.)
Installing VREXX
Once you unzip VREXX, youll see several files. VREXX includes Dynamic Link Libraries (DLLs), executables, documentation, comprehensive sample REXX programs, and help files. You can install them as directed by the included documentation:
1. Copy VREXX.INF to a BOOKSHELF help file directory specified in your CONFIG.SYS file.
2. Copy VREXX.EXE and the sample command files to a utility directory included in your PATH statement.
3. Copy VREXX.DLL and DEVBASE.DLL to a directory specified in your LIBPATH in CONFIG.SYS.
Or you can just unzip all of the VREXX files into a new directory and do all of your REXX development there without worrying about moving files or modifying paths.
Initializing/Housekeeping
Before calling VREXX functions, your REXX program must first load and initialize the functions by using RxFuncAdd and vInit() as illustrated in the sample REXX program. Also, on exit, your program should call the vExit() function to clean up system resources. Because it is important that your program clean up system resources properly, your code should establish error exits so that, in the event of abnormal termination, execution flow is properly routed through the cleanup code. The sample program has an example of error trapping.
Editing and Executing a REXX Program
You dont need to know much about programming to exploit REXX or the GUI functions introduced here. (REXX is IBMs SAA procedural language, and it has been implemented on VM, TSO, the AS/400, and OS/2. There are excellent REXX tutorials available; several of them are noted at the end of this article.) At this point, you just need to know how to edit the sample program and execute it.
Using your favorite editor, create a new member named XMPVREXX.CMD (all REXX programs must have the extension .CMD). Type the sample program code and save the file as ASCII text. To execute it, type the command name XMPVREXX in an OS/2 window. Better yet, to fully exploit the GUI concept, create a program object on your desktop (by dragging a program template from your templates folderrefer to your OS/2 reference for more information), attach the REXX command to it, then just double-click the new icon to execute your program. By ticking the
Start minimized and Close window on exit options in the settings notebook of your program object, your REXX code will operate like most native OS/2 applications.
Stem Variables
VREXX makes extensive use of stem variables. A stem variable is analogous to an array. Many REXX programs use stem variables to manage variable-length tables. Typically, STEM.0 contains the total number of elements, and STEM1 through STEMn contain the data. For example, to pass two lines of message text to the vMsgBox functionwhich requires a stem variable containing the text as a parameteryou can populate the MsgText stem variable as follows:
MsgText.0 = 2
MsgText.1 = This is the
first line of the message text
MsgText.2 = This is the
second line of the message text
You would then pass the name of the stem variable, in this case MsgText, to the function vMsgBox. (Refer to the VREXX Dialog Function Reference section of this article and the included sample code for more information on the actual vMsgBox invocation.)
Some of the VREXX functions use stem variables to return information as well. For instance, the vCheckBox functions returns a stem variable indicating the total number of items the user checked and the associated text of those checked items. Your REXX program could then interpret the returned variable stem.0. If it is zero, nothing was selected. If stem.0 was, for example, three, then stem.1, stem.2, and stem.3 would contain the text of the checked items.
Instead of enumerated subscripts, some functions return named stem variable subscripts. An example of this operation is vInputBox. When returning user- specified text, vInputBox sets the stem subscript named vstring to the entered text. To interrogate user input, your REXX program would examine the variable stem.vstring.
Some of the dialog functions described herevCheckBox, vInputBox, vListBox, vMsgBox, and vRadioBoxallow you to specify button options to appear in the pop-up dialog. The button options are OK, Cancel, OK and Cancel, Yes, No, and Yes and No. These button options are specified on the function call as 1, 2, 3, 4, 5, and 6, respectively. (Refer to the VREXX Dialog Function Reference section and included sample code for more information on the actual function call syntax.) The function returns the button the user selected; if the user pressed the OK button, the function returns OK; if the user pressed the cancel button, the function returns CANCEL, and so on.
Note that there are two ways to call a REXX function:
call func parm1, parm2, parm3 or
rc = func(parm1, parm2, parm3)
In order for the function to return a value, you need to specify the latter format so that a variable is set to the result of a function. In the case above, rc would be set to the function result. If the function was one that returned a button value, rc would reflect the button the user selected.
Sample App Ideas
A GUI function set empowers the OS/2 REXX programmer to easily develop sophisticated applications. For example, combined with the REXX EHLLAPI interface,
Buttons
you can graphically express AS/400 resources on your desktop. The opportunities are limitless. Start with the sample REXX program included here, which makes use of the Novell Send command to dispatch a message to any number of users. This sample application makes use of all of the fundamental VREXX dialog functions and is a great launch-point for your GUI REXX experimentation. Also, consider porting many of your OS/2 command-line applications to VREXX GUI applications. Start by replacing the SAY and PULL function calls with vMsgBox and vInputBox, respectively.
VREXX Dialog Function Reference
Here are some of the more common VREXX dialog functions you will need to use when you begin experimenting with VREXX. For a complete description of all of the VREXX functions, refer to the Visual REXX For Presentation Manager document included in the VREXX package. (Note: Before invoking VREXX functions, your REXX program must first load and initialize VREXX. Refer to the sample code elsewhere in this article for this procedure.)
vInitvInit initializes the VREXX environment. vInit is a prerequisite function for all VREXX functions. vInit returns the string ERROR if initialization fails. Sample execution: rc = vInit()
vExitvExit performs exit housekeeping and should be called on termination for any REXX program that has executed the vInit function. Sample execution: call vExit
vDialogPosvDialogPos allows your REXX program to specify where the subsequent pop-up will appear on the users terminal. vDialogPos accepts two parametersx and ywhich represent screen percentages where the x-coordinate 0 is the left edge of the screen and the y-coordinate 0 is the bottom edge. Thus, an invocation of call VDialogPos 50, 0 will place the pop-up window in left-to-right center (x-coordinate) and bottom (y-coordinate).
To center a dialog pop-up, specify 50,50.
vMsgBoxvMsgBox will probably be the VREXX function youll use most. It can display one to 10 lines of message text as well as OK, Cancel, Yes, and No buttons. Below is the code used to generate the vMsgBox. See Figure 1 for a picture of this window.
txt.0 = 6
txt.1 = This is a popup that can
support from one to 10 lines of
txt.2 = message text
as well as several button options.
txt.3 =
txt.4 =
txt.5 = If you would like to
exit, click the [CANCEL] button
now.
txt.6 = If you want to proceed,
click [OK].
button = vMsgBox(Sample vMsgBox,
txt, 3)
if button = CANCEL then signal
Cleanup_and_Exit
/* proceed with processing */
vFileBoxvFileBox is a handy function that displays a standard OS/2 file selection box with an optional file template (e.g., *.txt). The filename and entire path of the selected or specified filefor example, an input file or an output fileis then returned to the REXX program if the OK button is pressed.
Below is the code used to generate vFileBox. See Figure 2 for a picture of
this display.
button = VFileBox(Select a
names file to use, *.nms,
name)
if button = CANCEL then signal
Cleanup_and_Exit
selected_file = name.vstring
/* proceed with processing */
vRadioBoxvRadioBox displays a list of up to 10 items, each with a radio button from which the user may specify only one. The name of the checked item is then returned to the REXX program along with the specification of any button(s) selected.
Below is the code used to generate vRadioBox (see Figure 3).
list.0 = 3
list.1 = a. Use only first 9
list.2 = b. Review file now
list.3 = c. Abort operation
call VRadioBox Names file
limit exceeded!, list, 1 select
when
substr(list.vstring,1,1) = a
then do
/* User selected first radio button... */
end
when substr(list.vstring,1,1) = b
then do
/* User selected second radio button... */
end
otherwise
/* User selected third radio button */
end /* Select */
vListBoxvListBox displays a selection list for a user to review or select from. The name of the selected item is then returned to the REXX program along with the specification of any button(s) selected. Unlike vCheckBox and vRadioBox, vListBox has no display limit.
Below is the code used to generate vListBox (see Figure 4).
/* list names in list_box from
the names_data array populated
earlier */
height = 12
width = 20
list_box.0 = names_data.0
names_data_title = Charlies
Staff contents
do i = 1 to names_data.0
list_box.i = names_data.i
end i
call VListBox names_data_title,
list_box, width, height, 1
vCheckBoxvCheckBox displays a list of up to 10 items, from which a user may specify one or more by clicking a checkbox. The names of the checked items are returned to the REXX program along with the specification of any button(s) selected. Here is an example of displaying a checkbox. To see what the vCheckBox looks like, refer to Figure 5.
/* list names in check_box from
the names_data array populated
earlier */
recip_list.0 = names_data.0
do i = 1 to names_data.0
recip_list.i = names_data.i
end i
checked.0 = 1
checked.1 = recip_list.1 /*
Default checked is first entry */
button = VCheckBox( Choose
Recipients, recip_list,
checked, 3)
if button = CANCEL then signal
Cleanup_and_Exit
/* the function will set
checked.0 to the total number
of entries
checked and checked.1-n to the
selected entry text.*/
vInputBoxvInputBox displays a pop-up window with an input field for a user to enter data. The entered text is returned to the REXX program along with the specification of any button(s) selected. Figure 6 shows a sample vInputBox. Below is the code used to generate vInputBox.
/* Prompt user for message text */
width = 75
prompt.0 = 0 /* No additional lines
of message text */
prompt.vstring = Fredos been
involved in a terrible fishing
accident!
button = VInputBox(Type message text
and press [ENTER], prompt, width, 3)
if button = CANCEL then signal
Cleanup_and_Exit
message_text = prompt.vstring
What Lies Ahead
VREXX is simple way to add a sophisticated GUI interface to your OS/2 REXX command line programs. In my final OS/2 REXX article, which will appear in an upcoming issue of Client Access/400 Expert, Ill combine all of the concepts introduced up to this point, including screen-parsing with EHLLAPI. Well also introduce some advanced VREXX functions to create windows and draw into them to create an OS/2 desktop application that continually monitors AS/400 CPU utilization in a graphical manner.
References
IBMs EWS ftp site: ftp://software.watson.ibm.com/pub/os2/ews/vrexx2.zip ftp://members.aol.com/cmiksanek/xmpvrexx.zip Newsgroup: comp.lang.rexx
REXX EHLLAPI for Client Access/400 Optimized for OS/2, Client Access/ 400 Expert, March/April 1996
Harvesting Data from the AS/400 for Workstation Applications, Client Access/ 400 Expert, September/October 1996
OS/2 Procedures Language/2 REXX (available on softcopy in the OS/2 Information folder)
The REXX Language, A Practical Approach to Programming, Michael Cowlishaw, Prentice Hall (Cowlishaw is the designer of the REXX language.)
The REXX Language page at IBM Hursley: http://rexx.hursley.ibm.com/rexx/ rexx.htm
Figure 1: The vMsgBox
Figure 2: The vFileBox
Figure 3: The vRadioBox
Figure 4: The vListBox
Figure 5: The vCheckBox
Figure 6: The vInputBox
/*
To use this .cmd, ensure VREXX is correctly installed and the .nam
files are available.
For bext effect, create an OS/2 program icon that is minimized on
start-up and attach this .CMD file to it.
*/
diag = 0 /* diagnostic level */
@echo off
if Rxfuncquery( VInit) then call RXFUNCADD VInit, VREXX, VINIT
initcode = VInit()
if initcode = ERROR then signal Cleanup_and_Exit
signal on failure name Cleanup_and_Exit
signal on halt name Cleanup_and_Exit
signal on syntax name Cleanup_and_Exit
/* Define Button Aliases */
Button_OK = 1
Button_Cancel = 2
Button_OK_and_Cancel = 3
Button_Yes = 4
Button_No = 5
Button_Yes_and_No = 6
ver = VGetVersion()
/* Welcome popup */
txt.0 = 10
txt.1 = This is a sample application to familiarize the user with some of
txt.2 = the VREXX functions. Youll see that VREXX provides a robust
txt.3 = assortment of dialog, window, and graphic functions to give any
txt.4 = OS/2 REXX application a slick GUI
txt.5 =
txt.6 = This sample application displays a list of names and allows
txt.7 = the user to send a message to one or more using the Netware
txt.8 = SEND command. If your network does not support this command
txt.9 = or you otherwise choose to exit, click the [CANCEL] button now.
txt.10 = If you want to proceed, click [OK].
call VDialogPos 50, 50
button = VMsgBox(Welcome to the VREXX Sample Application, VREXX v||ver, txt, Button_OK_and_Cancel)
if button = CANCEL then signal Cleanup_and_Exit
/* Select Names File */
call VDialogPos 50, 50
button = VFileBox(Select a names file to use, *.nms, name)
if button = CANCEL then signal Cleanup_and_Exit
selected_file = name.vstring
rc = lines( selected_file)
if rc <> 1 then do
txt.0 = 2
txt.1 = ||selected_file
txt.2 = is not found or empty. Program aborting.
call VMsgBox File Error, txt, Button_OK
signal Cleanup_and_Exit
end
/* Read names file and populate stem variable */
names_data_title =
names_data.0 = 0
name_maxW = 0
do while lines( selected_file) = 1
line_of_file = linein(selected_file)
if names_data_title = then names_data_title = line_of_file
else do
names_data.0 = names_data.0 + 1
x = names_data.0
PARSE VALUE line_of_file with id , name
names_data.x = name
id_data.x = id
if length(name) > name_maxW then name_maxW = length(name)
end
end /* while loop */
user_decision_1:
/* Check if file exceeds maximum name limit of 10 (9 choices + all) */
if names_data.0 > 9 then do
list.0 = 3
list.1 = a. Use only first 9
list.2 = b. Review file now
list.3 = c. Abort operation
call VRadioBox Names file limit exceeded!, list, Button_OK
select
when substr(list.vstring,1,1) = a then do
names_data.0 = 9
end
when substr(list.vstring,1,1) = b then do
list_box.0 = names_data.0
do i = 1 to names_data.0
list_box.i = left(i||. ,4) names_data.i
end i
call VDialogPos 50, 50
call VListBox names_data_title|| contents, list_box, name_maxW*1.5, 12, Button_OK
signal user_decision_1
end
otherwise
/* Must be c so just exit */
signal Cleanup_and_Exit
end /* Select */
end /* Names > 9 */
/* Select Recipients */
recip_list.0 = names_data.0+1
recip_list.1 = names_data_title|| (all)
do i = 1 to names_data.0
x = i + 1
recip_list.x = names_data.i
end i
checked.0 = 1
checked.1 = recip_list.1
user_decision_2:
button = VCheckBox( Choose Recipients, recip_list, checked, Button_OK_and_Cancel)
if button = CANCEL then signal Cleanup_and_Exit
if checked.0 = 0 then do
txt.0 = 1
txt.1 = Check at least one recipient
call VDialogPos 50, 50
button = VMsgBox(User Error, txt, Button_OK)
signal user_decision_2
end
/* Prompt user for message text */
prompt.0 = 0
prompt.vstring = Fredos been involved in a terrible fishing
accident!
call VDialogPos 50, 50
button = VInputBox(Type message text and press [ENTER], prompt, 75, Button_OK_and_Cancel)
if button = CANCEL then signal Cleanup_and_Exit
message_text = prompt.vstring
/* Send specified message text to checked users*/
/* First, check for all request */
if checked.1 = recip_list.1 then do
checked.0 = 1 /* ignore any other checks on later redisplay */
do i = 1 to names_data.0
if diag > 0 then say SEND to id_data.i
/* Build Novell SEND command string */
parm = ||message_text|| to ||id_data.i
x:send.exe parm
end i
end
/* loop through and send to all checked */
else do
/* Loop through names_data for a match for checked.x */
/* When found i will then be the index into id_data */
do i = 1 to checked.0
do k = 1 to names_data.0
if checked.i <> names_data.k then iterate
if diag > 0 then say Checked.i: checked.i
if diag > 0 then say SEND to id_data.k
/* Build Novell SEND command string */
parm = ||message_text|| to ||id_data.k
x:send.exe parm
leave
end k
end i
end
call VDialogPos 50, 50
button = VMsgBox(Message sent to:, checked, Button_OK_and_Cancel)
if button = CANCEL then signal Cleanup_and_Exit
signal user_decision_2
Cleanup_and_Exit:
call VExit/* VREXX Cleanup */
Just_Exit:
exit 0
Figure 7: Sample VREXX Dialog Function Application
LATEST COMMENTS
MC Press Online