Stuff
OS/400 Edition
Volume 1, Number 19 -- October 24, 2002

Back to Basics: Windowed Subfiles


by Kevin Vandever

[The code for this article is available for download.]

display

I received several responses thanking me for the "Back to Basics" articles. Most responses had the same message: that we tend to write about new technology and forget about those who read our newsletter but have no opportunity to try out the new stuff. Many of you are buried in your daily battles, solving various IT issues, and don't have time to research technology, even if it's not new to OS/400. With that in mind, check out another oldie but goodie: windowed subfiles.

Windows 101

Windows are very powerful tools to use in displaying subfiles because they do more than just display information in a smaller format. They provide system resource save and restore functions, cursor control, and message handling--all without much effort by the programmer. With a couple of keyword entries, OS/400 will handle much of the work for you. A window is an area of information that overlays part of your display screen. You may view and update information in the window, as well as view information on the portion of the screen that the window isn't covering. When a window is displayed, it is the only part of the screen that is active; therefore, you cannot do anything with the screen that the window is covering until the window is removed. You can display up to 12 windows on a display. But no matter how many are displayed, only one can be active. Let's check out some basic concepts.

Keywords

There are five DDS keywords that a programmer has at his disposal to create windows and window subfiles. Not all are necessary, but with these five keywords, you can make OS/400 do a lot for you and create some very effective and efficient window applications.

WINDOW (window)--This keyword is the one required keyword to define a window in your application. It is used to define the window, to change the contents of a window, or to make an inactive window active again. You can define how the program acts when the cursor is outside the window borders, tell where messages are to be displayed, or simply point to another record format to get your attributes.

WDWBORDER (window border)--This keyword is used to define the color, display attributes, and characters of a window border.

WDWTITLE (window title)--This keyword is used to embed the title of the window inside the border. It allows you to define the text, color, and attributes for the title of the window, and will be embedded in the top or bottom of the border. Not all workstation controllers support text in the bottom of the border. Also, some do not allow left and right justification of title text.

RMVWDW (remove window)--This keyword is used to remove previous windows when a new window is displayed or an existing window is made active by redisplaying it.

USRRSTDSP (user restore display)--Using this keyword stops OS/400 from performing automatic save and restore functions on the underlying display when windows are displayed and removed. In most cases, you probably want to allow OS/400 to do its thing, because it requires no effort on the part of the programmer, but there are times when performance is more of an issue, and you may want to disable this activity. Preventing the automatic saving and restoring of the underlying display may increase your response time. You can also use this keyword when you want an overlaid window to pop up and become active. Or you can use it to make two windows seem like they are both active, which I did in "Back to Basics: Side-by-Side Subfiles."

Finally, Some Code

In my experience, window subfiles are most widely used as prompting tools and delete-confirmation screens. In this article, I will touch on the former. If a user is keying data and that data exists somewhere in a master file, why should he re-key the data, when he can look it up? Providing the user with a pop-up window, to display information and allow selection of that information, not only saves time but also helps avoid keying errors. I have provided a program, PNL001RG, which allows a user to key some data. In this program, the user can press the F4 key to prompt for name information from a master file. When the user presses F4, a window will pop up with a list of names. The user can then select a name and bring it back to his original display to fill in his data entry screen. Notice that the window is not part of display file PNL001DF. That resides in a separate display file. When the user presses F4, he is calling a new program to get his data. This technique is useful because it is likely that many applications will require a name-prompting tool. By coding the prompting program separately, you set it up to be used by other programs, without duplicating the code.

The user will press F4 when he wants to prompt for a name. The Return Cursor Location (RTNCSRLOC) keyword is not a subfile- or window-specific keyword, but I still feel the need to discuss it here. It is used to return the record format and field name that contain the cursor when control is returned to your program. This keyword has other parameters and many uses, and I invite you to look it up and check it out for yourself, but for now I'll stick to the record and field parameters. I may want my RPG program to know which field the user was on when he pressed F4. The parameters &FLD and &RCD are defined in the record format as hidden, 10-byte alpha fields, and they will be used to store the record and field where the cursor was when control is passed to the program. In my simple example, there is no need for this extra information, because there is only one field that can be prompted, but I provided it just in case you decide to expand my example.

If F4 (represented by the prompt constant) is pressed, the GETDTA subroutine is executed, which contains a call to program SFLWDWRG (the windowed subfile) passing one parameter. Nothing is really sent to SFLWDWRG; the DBIDNM parameter is a return variable used to house the customer number of the name that is selected by the user. If there is something in DBIDNM upon returning from SFLWDWRG, it is used to CHAIN to the data file and retrieve the appropriate information for the screen. In this example, there is only one prompting program to be called, SFLWDWRG. No matter what field your cursor is on, when F4 is pressed, the name window will display. If I wanted to prompt for different information, I could use the field name returned to my program by the RTNCSRLOC keyword to determine what program to call. I didn't include the code in the program, but you could use the following structure to display different windows, depending on cursor location.

     
      C                   if        cfkey = prompt
     C                   select
     C                   When      FLD = DBFNAM 
     C                   exsr      getdta

     C                   When      FLD = DBADD1 
     C                   exsr      XYZ

     C                   endsl
     C                   endif

Now let's take a look at the actual windowed subfile for this example.

Selection List

SFLWDWDF is the DDS for my windowed subfile. Instead of providing the user a simple load-all subfile from which to choose his data, I am going to add a twist. That twist is in the form of a selection list. A selection list subfile is perfect for prompting and returning data. What differentiates a selection list subfile from a regular subfile is its ability to restrict the user to one choice or allow many choices. Also, with a selection list, you can allow simple cursor maneuvering and data selection without adding an input field.

My example is a load-all subfile, as determined by SFLSIZ and SFLPAG not being equal. You'll also notice that there is no ROLLUP or ROLLDOWN keyword--another indication that this is a load-all subfile. I defined a 1-byte, hidden field, CTLFLD, and assigned it as the selection list choice control field, with the SFLCHCCTL keyword. This will allow OS/400 to ensure that selection list rules, determined later in my control record format, are enforced. I also defined another hidden field, DBIDNM. This is my customer number, and although it will not be displayed, it is what I will pass back to the calling program when the user has made a selection. The last field is a 40-byte alpha field called FULLNM. This field will contain the first and last names from the data file. The reason I decided to concatenate the two fields is because of a restriction with selection lists. You can only have one output field when using a selection list. Because I want both names to be displayed in the window, I concatenate them into one field. I'm so smart! You may have also noticed that there is no input field. Selection will be accomplished by OS/400 based on cursor location. There's no need to interrogate data inside the application.

The WINDOW keyword contains the coordinates for starting position; I use the parameter *DFT. This will allow my window to display in relation to where the cursor is located on the display. If the cursor is at the top of the screen when F4 is pressed, the window will display underneath the cursor. If the cursor is at the bottom, the window will display above it. You get the picture. I define the window as 14 lines long and 44 characters wide and tell it that I don't need a message line.

The next windows keyword you see is the WDWBORDER keyword. This allows you to define the borders of your window. If you leave the parameters blank in the keyword, you will get the default windows border that you see in many IBM-supplied windows. I decided to explicitly define the border. You can define the characters, color, and attributes of your window. In this example, I am going use the default characters and attributes, but I am going to change the color to pink. (It's my wife's favorite color, OK?) The WDWTITLE keyword allows you to insert text into your border. The text can be placed on the top or the bottom, and can be on the left, center, or right. Some workstation controllers don't support bottom border titles or non-centered top border titles. You can still code them, and if your controller doesn't support them, they will be ignored. My first border title is type *TEXT, centered on the top, and colored white. Centered and *TOP are the defaults for this keyword; that is why I didn't explicitly define them. The second WDWTITLE keyword allows me to add text to the bottom of my border. Since I can't add a separate record format to display the valid function keys like I can with a regular subfile, I need another way. A bottom window border is my way. I am going to add the *TEXT data F12=Cancel, color it blue, and place it on the bottom border of the window. Left-justified placement is the default for bottom window borders, so I don't have to explicitly define it.

Before I go on, I may have lost some of you when I quickly brushed over the fact that I can't have a function key record format. Each record format that contains the WINDOW keyword becomes a window. If I create a record format to display function keys without the WINDOW keyword, it will be written to the original display. If I add the WINDOW keyword or reference a format with the WINDOW keyword, it becomes its own window; so the only way to show the user the function keys at the bottom of the windowed subfile is to do so in the border.

The Subfile Single Choice (SFLSNGCHC) keyword tells OS/400 that only one choice can be selected and returned from the list. The user can scroll through and try to select many entries, but only the last entry selected is the one returned when Enter is pressed. The Restrict Cursor (*RSTCSR) keyword restricts the cursor to the list, so the user can use the arrow keys to scroll down the current page without leaving the list. When the cursor reaches the bottom of the list, it automatically goes back to the top of the list. The Subfile Cursor Relative Record number keyword (SFLCSRRRN) and its parameter return the subfile relative record number that the cursor is on when control is returned back to the RPG program. The parameter &RRN1 is defined as a hidden field of five zoned decimal characters. Your program will use the relative record number to send the correct information back to the calling program.

The ASSUME keyword, inside the ASSUME record format, is used to tell OS/400 to assume that the record is already written when the display file is open. That way OS/400 won't attempt to erase the current display before displaying the window. You cannot use the ASSUME and WINDOW keywords in the same record format. Because of this, I provided the ASSUME keyword with its own format and defined one non-display field. I never have to reference this record in my RPG, but by placing it in my DDS, I accomplish writing the window without erasing the current display. It's now our little secret how to fake out OS/400.

Programming the Selection List

The DDS does most of the work, but there are a couple of things to talk about in the RPG.

As you can see, the RPG doesn't care if you are using a regular subfile or a selection list subfile. As a matter of fact, the only hint you get that this is a selection list, and it's a slight hint at that, is to notice that I concatenated the first and last names into FULLNM. This does not guarantee that this is a selection list, but it is the closest thing to a clue. Other than that, the load-all routine works like any regular subfile. In the main routine, I clear the subfile, load the subfile, and then display it. I don't even bother with a DOW or DOU loop, because control only needs to be passed back to the program once before returning to the calling program. The user will either select a record and press Enter or press F12 to cancel. In either case, the program only needs one pass through it. If the user scrolls through the subfile, that scrolling will be handled by OS/400. If neither F3 nor F12 are pressed, the program chains to the WINDOW1 subfile record format with the relative record number returned by the RTNCSRLOC keyword. By chaining the subfile, I can get the customer number (DBIDNM) of the selected record and pass it back to the calling program. If F3 or F12 is pressed, the else clause is executed, which zeros out the customer number before returning to the calling program. If you look back at PNL001RG, you will see that it checks for DBIDNM > 0 before it does anything.

Who Needs Microsoft to Enjoy Windows?

There you have it. I have shown you a little about windows, subfiles in windows, and a specifics subfile called a selection list. I urge you to investigate this further. There is a lot of information on what OS/400 does under the covers for you with windows and how you can take on that control yourself, if you choose. There are also some cool things that you can do with selection lists that I didn't cover in this article. You can even employ a not-widely-used parameter on the SFLEND keyword to provide a scroll bar inside your window. So there is plenty to mess around with. Go forth and seek knowledge.


Sponsored By
PROFOUND LOGIC SOFTWARE

Don't be left behind!

Thousands of programmers have adopted RPG-Alive, and are now able to read and understand RPG code 2 to 3 times faster.

To try RPG-Alive on your system, visit http://www.RPGAlive.com/now

"I am very happy with RPG-Alive! It's a terrific productivity booster!" says Brian Johnson of Help/Systems.

See other user testimonials at http://www.rpgalive.com/testimonials.html


THIS ISSUE
SPONSORED BY:

Jacada
Magic Software
ASNA
Original Software
Profound Logic Software
WorksRight Software


BACK ISSUES

TABLE OF CONTENTS
Add a Safety Net with Journalized Data Queues

Creating Editable Web Pages

Using Data Queues in VARPG

Sprinkle GUI on your Green Screen Salad

Back To Basics: Windowed Subfiles

Easy Display File Printing


Editors
Shannon O'Donnell
Kevin Vandever

Managing Editor
Shannon Pastore

Contributing Editors:
Howard Arner
Joe Hertvik
Ted Holt
David Morris
Richard Shaler

Publisher and
Advertising Director:

Jenny Thomas

Advertising Sales Representative
Kim Reed

Contact the Editors
Do you have a gripe, inside dope or an opinion?
Email the editors:
editors@itjungle.com



Last Updated: 10/24/02
Copyright © 1996-2008 Guild Companies, Inc. All Rights Reserved.