Susan Graham
Microsoft Corporation
January 1997
Ever since the release of Microsoft® Visual FoxPro™ there has been continuous discussion among Fox developers about the pros and cons of moving FoxPro® 2.x code into the new object-oriented programming (OOP) paradigm. Should one convert the 2.6 code? Should one just throw it all away and rewrite everything? The purpose of this paper is to:
If your FoxPro 2.x application has been running well—it's been through several versions, it's stable, and needs no new functionality—you need to ask yourself if there is really a reason to take the time and effort to migrate that application to Visual FoxPro. However, since the reality of most development projects is that they are never finished, you need to consider the advantages and disadvantages of the conversion process to determine which path is right for your application: convert or rewrite.
You want to move your applications into Visual FoxPro so that you can begin to take advantage of OOP, the new development environment, and the new database features of Visual FoxPro 5.0.
Most FoxPro version 2.x programs coded in traditional procedural style will run with minor modifications in Visual FoxPro. Conversion is a viable option for some developers.
Consider making the transition to an OOP programming style if the following conditions are true:
Here are some issues to consider before deciding whether to convert:
Once you have decided to migrate your application from FoxPro 2.x to Visual FoxPro, there are three basic approaches you can take:
Approach | Advantages | Disadvantages |
Minimalist—Compile and run, no conversion | Least amount of work to get apps running in 5.0 No further development time and effort |
FP 2.6 architecture, not OOP Old User Interface, not Windows 95 UI Cost of maintenance/ improvement may be high |
Hybrid—Convert and modify | Old code still usable Begin to take advantage of new OOP functionality Take advantage of new VFP 5.0 functionality UI gets new look and feel (end user sees a difference) |
Mix of 2.6 and 5.0 paradigms Hard to maintain |
Total rewrite | More powerful design tools Database features Tap the power of VFP 5.0, such as event handling, common code syntax, and other benefits associated with OOP Re-architect your application Investment of time and money |
OOP learning curve |
Your existing FoxPro 2.6 application should compile and run with few problems if you follow these steps:
Using this minimal approach allows you to continue running mission critical applications as you take the time to move into the new OOP paradigm.
This approach uses the Visual FoxPro Converter to "migrate" your 2.6 screen sets to backward-compatible Visual FoxPro form sets (as opposed to New Event Model form sets). Once screens are converted, continue the conversion so they become "true" Visual FoxPro forms that are able to use the new event model and other features. More on this later.
Converting from the project level is usually the desirable way to convert an application. Converting a project handles everything at once and really is the only way to change multiple screen sets into a Visual FoxPro form set. The alternative is to convert individual screens, reports, and so on one at a time. This has the advantage of allowing you to move the process along more carefully. It also makes it possible to selectively convert some screens with the Visual conversion, some with the Functional conversion (see below).
If you have used the Power Tools in FoxPro 2.6, the following FoxPro file types will convert:
Reports
DOS reports will only run unconverted, as in FoxPro 2.6 for Windows; you cannot edit DOS reports in Visual FoxPro.
Genpd.app can be recompiled and run, but Visual FoxPro will not support these printer drivers. The functionality has been replaced in the operating system.
Take note of the new functionality of the REPORT FORM command. See the Help file for REPORT FORM, ASCII and REPORT FORM, PREVIEW.
CONVERT.APP
The Convert.app application is installed by default in the Visual FoxPro home directory. Because it would have been impossible to account for all the possible conversion issues, the source code for the compiler is distributed with Visual FoxPro in the \VFP\Tools\Convert directory. You can customize it for your particular needs by setting the system variable _CONVERTER to your version of the Convert.app.
When you attempt to modify a 2.6 screen or project, Visual FoxPro 5.0 detects the older version and automatically loads Convert.app and displays this screen:
Even though there is an option to save backup files in a directory named "Old," it is a better idea to work on a copy of your original 2.6 files rather than rely on the \Old directory. The primary reason for this is the path issues that you'll have to deal with when your directory structure is changed to include a top level \Old directory.
Choosing between Functional or Visual conversions is one of the most important decisions you must make.
The Functional conversion makes it easier for the developer in the short run, but can require more work to take advantage of the new features of Visual FoxPro 5.0. The Converter makes forms backward compatible, with attributes unique to this type of form (more later).
The Visual conversion duplicates in Visual FoxPro 5.0 all visual components of a project (forms, buttons, and so on), but none of your existing snippet code (Open, Valid, et cetera.). All the code from the original FoxPro 2.6 snippets is copied to a non-compilable .prg file. You will have to cut and paste your procedural code into the appropriate events and methods of the Visual conversion. But you won't have to modify the converted form to take advantage of the new event model.
If you choose Functional conversion, the conversion process performs these steps:
The following table summarizes how 2.6 screen events are converted to VFP 5.0.
FoxPro 2.6 screen event | Converted Visual FoxPro 5.0 event |
Setup—#Section 1 | FormSet.Load |
Setup—#Section 2 | Form.Load |
Activate | Form.Activate & FormSet.Activate |
Deactivate | FormSet.Deactivate |
Show | FormSet.ReadShow |
When | FormSet.ReadWhen |
Valid | FormSet.ReadValid |
Cleanup | FormSet.Unload & SPR for procs/functions |
The READ keywords CYCLE, LOCK, MOUSE, SAVE, and TIMEOUT are moved to FormSet properties with the names ReadCycle, ReadLock, ReadMouse, ReadSave, and ReadTimeout.
The Converter creates a file with an .spr extension for each converted screen. This file is different from a FoxPro 2.6 .SPR file. In FoxPro 2.x, the .spr file was generated code based on what was found in the .scx. In Visual FoxPro, the .spr file is a "wrapper" file that includes the correct DO FORM command required to run the screen code. Here is an example of the .spr created after converting Laser.scx from the FoxPro 2.6 samples:
*- [CONVERTER] Declare arrays
EXTERNAL ARRAY ltags
EXTERNAL ARRAY rats
EXTERNAL ARRAY studs
EXTERNAL ARRAY titlelist
*- [CONVERTER] Declare variables for record pointers
PUBLIC _iconvLaserGoToPlaceHolder
EXTERNAL PROC laser.scx
DO FORM "laser.scx" NAME _RH21148KX LINKED
*- [CONVERTER] Begin CLEANUP and other procedures from 2.x Form
PROCEDURE setltags
DIMENSION flds(256), ltags(256)
ltags(1) = "Record#"
FOR i = 2 TO 256
IF LEN(TAG(i-1)) = 0
i = i - 1
DIMENSION ltags(i)
EXIT
ELSE
ltags(i) = TAG(i-1)
ENDIF
ENDFOR
ord = "TITLE"
SET ORDER TO TITLE
SHOW GET ord
*- [CONVERTER] End CLEANUP and other procedures from 2.x Form
The DO FORM command has two very useful clauses: NAME and LINKED. The NAME clause specifies a variable or array element with which you can reference the form or form set. However, if you specify a variable that doesn't exist, Visual FoxPro automatically creates it. When you specify an array element, the array must exist before you issue DO FORM. If the variable or array element you specify already exists, its contents are overwritten.
If you omit the NAME clause, Visual FoxPro creates an object type variable with the same name as the form or form set file.
Include LINKED to link the form to the variable associated with it so that the form is released when the variable goes out of scope. If you don't include LINKED, a form can still be active, even though there is no object variable associated with the form.
The Converter places these files in the following locations in the Project Manager:
FoxPro 2.6 files | Project Manager tab |
.prg and .spr files | Code tab |
.scx and .sct files | Documents tab |
.frx and .lbx files | Documents tab |
In the Functional conversion, each converted form is in FoxPro 2.6 READ-compatibility mode. Each form set contains one page frame that contains one page for each read level of the original screen. This format was necessary to account for any and all READ LEVELS your FoxPro 2.6 code might have.
The FormSet WindowType property identifies the READ compatibility mode of converted forms. If forms are in READ compatibility mode, the WindowType property is either 2 (Read) or 3 (Read Modal), and the form set takes on the READ qualities of a 2.6 screen set. Execution stops when a DO FORM or SHOW command calls the form.
The WindowType properties that relate to 2.6 screen compatibility are only available with functionally converted 2.6 screens. When screens are converted Visually or are created in Visual FoxPro, this WindowType property only relates to standard Visual FoxPro modeless and modal behavior and cannot be set to 2 and 3. The only time you will see form set WindowType properties with READ capabilities is in a Functionally converted form set.
In FoxPro 2.6 READ compatibility mode, variables created in the Load event of a form set with WindowType set to 2 or 3 are scoped to the form set and visible to the entire form set, its forms, and its controls. You can control the visibility of variables created in other form set events or methods by using the PRIVATE, PUBLIC, or LOCAL commands.
Environmental settings are automatically defined in the form set Load event and the current record pointers are saved in public variables during the form set Unload event. The data environment of the form is updated with all appropriate FoxPro 2.6 view environment objects, such as the table aliases, index orders, and relationships. The FoxPro 2.6 generator directives for automatically opening and closing the tables are moved to the AutoOpenTables and AutoCloseTables properties in the DataEnvironment object.
FoxPro 2.6 screen feature | Visual FoxPro feature |
Screen set | Form set |
Screen | Form contained in a form set |
READ level | Page contained in a page frame |
READ screen mode | WindowType property = 2 |
READ MODAL screen mode | WindowType property = 3 |
FoxPro 2.6 screen snippet | Visual FoxPro property or event |
Form Level | |
Open Files | FormSet.AutoOpenDE |
Close Files | FormSet.AutoCloseDE |
Window Name | FormSet.WinName.Name |
Window Title | FormSet.WinName.Caption |
Width | FormSet.WinName.Width |
Height | FormSet.WinName.Height |
Left | FormSet.WinName.Left |
Top | FormSet.WinName.Top |
Center | FormSet.WinName.AutoCenter |
Border | FormSet.WinName.BorderStyle |
Moveable | FormSet.WinName.Moveable |
Close | FormSet.WinName.Closeable |
Icon | FormSet.WinName.Icon |
HalfHeight Title Bar | FormSet.WinName.HalfHeightCaption |
Color | FormSet.WinName.BackColor |
Wallpaper | FormSet.WinName.Picture |
Minimize | FormSet.WinName.MinButton |
Font | FormSet.WinName.FontName/FontSize,Fontbold |
Environment | FormSet.WinName.DataEnvironment |
You must convert FoxPro 2.6 reports (.frx files) to Visual FoxPro reports in order to access files in the Report Designer and to add Visual FoxPro functionality.
To convert a FoxPro 2.6 report, use the MODIFY REPORT command. The conversion process performs these steps:
If the FoxPro 2.6 report was created without an ENVIRONMENT clause, the AutoOpenTables and AutoCloseTables properties of the converted report are set to false (F).
If the FoxPro 2.6 report was created with an ENVIRONMENT clause, the AutoOpenTables and AutoCloseTables properties of the converted report are set to true (T). The Destroy event of the converted report contains the following code:
THIS.OpenTables && Opens all the tables
THIS.Init && Runs the Init code of the converted report's
&& DataEnvironment
After converting a report, Visual FoxPro opens the Report Designer so you can add Visual FoxPro functionality to the converted report.
After you convert a FoxPro 2.6 screen (.scx) file, you should check for the following conditions:
IF somecriteria
RETURN
ENDIF
IF somecriteria
RETURN .F.
ENDIF
You can completely change converted FoxPro 2.6 screens to the Visual FoxPro event model:
Note When you make this change, the READ compatibility properties and events are no longer available and the WindowType setting cannot be changed back.
To run the form directly, move code from the generated .spr file to appropriate methods in the form so you can run it with the DO FORM command.
In FoxPro 2.6, the foundation READ was used to emulate event-driven programming by providing an event loop and handler. In Visual FoxPro, you can take advantage of the native event loop by converting your foundation READs.
Replace any foundation READ in the main program with a READ EVENTS command. For example, include a READ EVENTS command in a .prg program that runs your main form or form set.
Place a CLEAR EVENTS command in the form, menu, or program event that ends the program. For example, assign a CLEAR EVENTS command to the Exit menu item.
You may have code that closes things such as tables and windows neatly. When you move into the new event model you won't need any of this code, because Visual FoxPro handles it all for you.
Also, check the settings of the form set WindowType property for your converted screens. In FoxPro 2.6, you coordinated screens through READ and READ MODAL statements. These statements are converted to the WindowType property when you convert your files. For backward compatibility, the property is automatically set to 2 or 3, depending on the READ mode of the original screen. To enable full event model functionality once you've converted foundation READs, change the READ compatibility mode of screens, remove extra pages and page frames, and change form methods.
User Interface
In Visual FoxPro, the TAB key navigates between controls. To move through options in a list box, use the arrow keys.
Some hot keys have changed to conform with the Windows 95 user interface guidelines.
FoxPro 2.6 | Visual FoxPro | Definition or difference |
n/a | CTRL+N | Create a new file |
CTRL+N | CTRL+O | Add a record to a Browse window |
CTRL+O | CTRL+E | DO program from within edit window |
Language
FoxPro 2.6 ignores anything longer than 10 characters, but Visual FoxPro supports and recognizes the longer variable names. If you took advantage of this FoxPro 2.6 "feature," you need to modify your code. To see the difference, run this code in FoxPro 2.6 and then in Visual FoxPro:
clear
store "hello" to clcustomer1
?clcustomer1
?clcustomer
store "goodbye" to clcustomer2
?clcustomer2
?clcustomer
Visual FoxPro also supports longer file names. In FoxPro 2.6 you could have a table called Mynewtab.dbf and this command would work fine: USE MYNEWTABLE. In Visual FoxPro 5.0, this command used on the same file will generate a "file does not exist" error.
There are now 32767 work areas! This affects code that loops through work areas (up to 225). Use AUSED( ) instead. Note that this affects SELECT(1). See what you get by issuing this command in FoxPro 2.6 and Visual FoxPro 5.0.
Table and database differences
Visual FoxPro distinguishes between tables and databases. Although FoxPro 2.6 tables are fully functional in Visual FoxPro, if you modify the table structure of FoxPro tables to take advantage of any of the new Visual FoxPro 5.0 table features like acceptance of null values, they are saved as Visual FoxPro tables. Note that if you merely change things like field size, field names, or only add or delete fields the table is maintained as a FoxPro 2.6 file.
FoxPro 2.6 table structure feature or functionality | Visual FoxPro structure feature or functionality |
Character field with NOCPTRANS characteristic | Character (BINARY) field type |
Date fields | Date data type, DateTime data type |
General field size | Now 4 bytes |
Memo field size | Now 4 bytes |
Memo field with NOCPTRANS characteristic | Memo (BINARY) field type |
Numeric fields | Currency data type, Double field type, Float field type, Integer field type, or Numeric data type |
OLE data in a General field | OLE Bound control |
The structure of Visual FoxPro project (.pjx), screen (.scx), report (.frx), and label (.lbx) files differ from the structure of FoxPro 2.6 files. For details on the structure of Visual FoxPro table files created in the Project Manager, Form Designer, Report Designer, and Label Designer, see Table Structures of Table Files. The filespec directory contains reports you can print out that have specific details of the structures of Visual FoxPro, as well as FoxPro 2.x, tables.
Null values
Visual FoxPro tables can accept null values. To prevent errors generated by attempts to store null values to FoxPro 2.6 variables or to Visual FoxPro controls, initialize variables or arrays. To prevent users from attempting to store null values to tables, you can disable the NULL entry key combination by using the following statement:
ON KEY LABEL CTRL+0 *
Visual FoxPro allows you to use views as you would tables or queries. If you build a view in Visual FoxPro without qualifying the table name to a database, you'll get an error when you try to modify the view in the View Designer. To ensure that you can use or modify views in all versions of Visual FoxPro, use CREATE SQL VIEW with the FROM clause as in the following example:
FROM testdata!products && testdata is the database name
&& products is the table name
When you specify the source this way, Visual FoxPro searches for the table both in the open database list, including the current and any non-current databases, and in the default search path for the table.
Visual FoxPro does not change the structure of FoxPro tables unless you add the table to a database or add a new data type or enable acceptance of null values. Once you change the structure of a table by adding a new data type such as DateTime, or by enabling null values in a field, Visual FoxPro modifies the table file structure, making the file unrecognizable to FoxPro 2.6.
You can create a FoxPro 2.6 table from a Visual FoxPro table by using the COPY TO command with the TYPE clause and the FOX2X keyword, as in the following example:
* A Visual FoxPro table
USE vfptable.dbf
* Creates a FoxPro 2.6 table
COPY TO fp26tabl.dbf TYPE FOX2X
To copy a FoxPro 2.6 table structure from a Visual FoxPro table, use COPY TO and the NEXT clause, as in the following example.
* Creates an empty FoxPro 2.6 table
COPY TO fp26tabl.dbf NEXT 0 TYPE FOX2X
Visual FoxPro changes all null values in NULL-enabled fields to either 0 or blank, and creates a structure recognized by FoxPro 2.6. Visual FoxPro also converts Integer, Double, and Currency types back to Numeric, and changes DateTime to Date type.
Well, not exactly total. You can, of course, keep the data structures and business rules you have already developed. But you will want to take the time to redesign your application to take advantage of OOP structure and functionality. This is the most costly (and time consuming) approach, but it is also the most powerful and flexible. This approach allows you to take advantage of all the new features of Visual FoxPro 5.0. In addition, you will find that you can eliminate hundreds (thousands?) of lines of code because Visual FoxPro 5.0 has built-in functionality that you once had to code yourself.
Many developers claim unequivocally that a total rewrite is the way to go, especially with applications that are simple. With the new features of Visual FoxPro 5.0 you will find elegant solutions to problems you needed "kludges" for in FoxPro 2.6. You will begin to develop class libraries to use again and again in future application development.
The best investment of time and resources will be in the design phase of your new application. Learn OOP techniques and learn how they work in Visual FoxPro.
Take advantage of one of Visual FoxPro 5.0's coolest new features to use information from your 2.6 application: Visual FoxPro 5.0's ability to be a custom OLE Server will enable you to use your 2.6 application to provide information to another application.
The Laser sample that ships with FoxPro 2.6 is a laser disk library manager program. The main program is Laser.spr. To turn this into an OLE object callable from Visual Basic or Microsoft Excel, create a new project in a new main program:
ox = create("laser")
define class laser as custom olepublic
proc init
cd d:\fpw26\sample\laser && change dir to the right place
set path to data
this.application.visible = .t. && make us visible.
proc doit
do laser.spr
enddefine
Add the new Laser.spr to the project. You'll need to manually add any supporting files, like .bmp files, to the project. Then, you can try:
OX = Createobject("laser.laser")
and then:
OX.Doit.
The laser application is now running as an OLE Automation server! If you modify the Laser.spr program so that it doesn't close the LASER table when the READ is finished, then you can query what laser disc title was chosen:
?ox.application.eval("title")
If your application is working well in 2.6, you don't need to add features to your application, and your investment in time and cost of upgrading, you might wish to stay with FoxPro 2.6. However, you will want to move your applications into Visual FoxPro so that you can begin to take advantage of all its new features and functionality. In addition to the features that came with Visual FoxPro 3.0 (OOP, database features, and more.). Visual FoxPro 5.0 adds improved performance, the new development environment, and new database features of Visual FoxPro 5.0