Character-GUI Conversions Using Batch Procedures

Your existing code base is your biggest asset, but it is also your biggest hurdle in moving to a GUI environment. The GUIBuilder Visual Programming Environment offers some help with the ability to cut-and-paste code from existing programs into a new GUI program. But if you have a lot of data entry programs and you'd like to put together a batch update procedure, you'll need to step outside of the Visual Programming Environment. If your existing code base and screen layouts are sufficiently well structured, you might be able to partially automate the conversion process. This is possible because the components that make up GUIBuilder are implemented as independently callable procedures. Here's a very brief overview of the process:

  1. Write a program to read your existing screen formats (from screen files or directly from the program source) and write ASCII Resource files. See "ResCompiler: Another Path to the User Interface Dictionary" at <https://www.basis.cloud/advantage/mag-v2n1/rescompiler.html>. One way to simplify this process is to create your ASCII Resource files with the unit of measure defined as "Characters" (as opposed to "Pixels" or "Semichars"). Because character screens do not map directly to GUI screens, you'll need to make some decisions about how to convert various screen elements. The easiest way to start is to convert static text to TEXT controls, string fields to INPUTE controls, numeric fields to INPUTN controls, and boxes and lines to GROUPBOX and LINE controls. For a more complete discussion of this process, see "A New Approach to Going GUI" at <https://www.basis.cloud/advantage/mag-v1n3/goinggui.html>.

  2. Compile each ASCII Resource file (sample.arc) to a Binary Resource file (sample.brc) using the ResCompiler program (rescomp.exe).

  3. Generate the framework for a GUIBuilder control file (sample.gbf) by calling the GUIBuilder module "gb_func::gb__make_gbf."

  4. Write a program to analyze your legacy program and extract pieces that can be used in a GUI version of the program. To help with this process, you might find a use for the called program "_label", which converts all line number references in a program to line label references, and the pro5lst.exe utility, which converts a program file to text. As you extract these pieces, write them to the GUIBuilder control file (sample.gbf) using the function fngb__put_code$() included in gb_func.src. Think in terms of the following functional areas:

    Initialization. Open data files; define record templates and other global variables. Note that GUIBuilder generates an ENTER line with a single variable (gb__arg$), which can have an associated template to allow for passing multiple values. Initialization code is written to the GUIBuilder control file with a header of [Init].

    End of Job. Close data files; clean up global variables. End of Job code is written to the GUIBuilder control file with a header of [EOJ].

    Event handlers. This is the most difficult, because this is where the structures of character and GUI programs are the most different. As a very rough approximation, consider using the "Got Focus" and "Lost Focus" events.

    • "Got Focus": This event is available for all data entry fields (INPUTE, INPUTN, TEXT, and TXEDIT). It's triggered as the user enters the field.

    • "Lost Focus": Also available for all data entry fields, this event is triggered when the user leaves a field. Do not assume the user is necessarily finished with a field just because you got a "Lost Focus" event. It could mean (for example) that the user just called up the help system to check something.

    • In a GUI program, the most reliable way for users to inform you that they are finished with a given screen is to push an "OK" button. If you have a standard data entry frame, you might want to consider automatically generating a series of buttons to handle standard functions (Update Record, Delete Record, Print Record, etc.).

    Subroutines, Functions, and non-executing code blocks. These can be relatively easy to move into the GUIBuilder control file, but it's up to you to ensure that they're being used properly. Subroutines must include a label and a return statement, and non-executing code blocks (IOLIST, DATA, and TABLE) should have an associated label so you can refer to them from elsewhere in the program. These code blocks are written to the GUIBuilder control file with a header of [Function (unique_name)]. If you have standard subroutines, functions, IOLISTs, TABLEs, or other blocks of code that should be included in all of your programs, put them in the standard include file gb_std.cod. This file is merged into the end of all programs generated by GUIBuilder. The standard error and escape handlers are stored in ASCII text files (gb_err.cod and gb_esc.cod); if necessary, you can replace them with customized error and escape handlers.

  5. Confirm that the structure of the GUIBuilder control file (sample.gbf) is acceptable by calling the GUIBuilder module "gb_func::gb__val_data ."

  6. Generate the final program (sample.bbx) by calling the GUIBuilder module "gb_func::gb__build_program."

  7. At this point, the generated GUI program can be maintained within the GUIBuilder Visual Programming Environment.