Moving from FoxPro 2.x to Visual FoxPro 5.0

Susan Graham
Microsoft Corporation

January 1997

Overview

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:

Convert or Rewrite?

If it ain't broke . . .

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.

OK, it ain't broke, but . . .

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:

Issues to Consider

Here are some issues to consider before deciding whether to convert:

Approaches

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

Approach 1: Minimalist—Compile and Run, No Conversion

Your existing FoxPro 2.6 application should compile and run with few problems if you follow these steps:

  1. Create a new project in Visual FoxPro 5.0.

  2. Add your main PRG. (Note: Do not use an SCX as your main program. If you do, Visual FoxPro 5.0 will invoke the Converter.)

  3. Build the project.

  4. Add files not pulled in by the Project Manager (bitmaps, #includes, etc.).

  5. Build your application.

Using this minimal approach allows you to continue running mission critical applications as you take the time to move into the new OOP paradigm.

Approach 2: Hybrid—Convert and Modify

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 FoxPro 2.6 projects

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:

  1. Copies the original project files to a new subdirectory named Oldx in the original .pjx directory and automatically increments x as you convert more projects.

  2. Converts the project and all associated screens, reports, and labels to Visual FoxPro format. New forms have the .scx and .sct extensions. Original files are given .s2x and .s2t extensions.

  3. Moves code snippets to appropriate event and method code.

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.

Form sets and control properties

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

Using the DO FORM command

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 WindowType property

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.

Variable scoping in load events

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.

Mapping

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

Modifying 2.6 reports

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:

  1. Adds a user field to the .frx file.

  2. Changes any Memo fields from 10 bytes to 4 bytes.

  3. Adds records to support the data environment of the report. FoxPro 4.2.6 environment records convert to data environment records.

  4. Sets the AutoOpenTables and AutoCloseTables properties of the Data Environment and the Destroy event of the new report for backward compatibility with the ENVIRONMENT clause of the FoxPro 2.6 REPORT command.

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.

Gotchas with forms

After you convert a FoxPro 2.6 screen (.scx) file, you should check for the following conditions:

Post Conversion—Extending a Functionally Converted Form

You can completely change converted FoxPro 2.6 screens to the Visual FoxPro event model:

  1. Change the WindowType property from 2 (Read) to 0 (Modeless), or from 3 (Read Modal) to 1 (Modal).

    Note   When you make this change, the READ compatibility properties and events are no longer available and the WindowType setting cannot be changed back.

  2. If you have a single form, move FormSet event code to the matching or appropriate form events and remove the FormSet.

  3. Move code from the READ-compatibility events to the form events and methods that are now available, taking event firing sequences into account.

  4. Change CLEAR READ to RELEASE THISFORMSET or RELEASE THISFORM.

  5. Change SHOW GET to <object>.Refresh.

  6. Change SHOW GETS to THISFORM.Refresh or THISFORMSET.Refresh.

  7. Change SHOW GET for List and Combo boxes to <object>.Requery.

  8. Move READ SHOW and READ WHEN to the form set Load event.

  9. Move READ ACTIVATE and READ DEACTIVATE to the form set Activate and Deactivate events.

  10. Move READ VALID to the QueryUnload event.

  11. Use copy and paste to move all objects from the page to the form itself.

  12. Remove extraneous page and page frame controls.

  13. Move parameters from the screen Load event to the Init event of the form.

  14. Adjust scoping of variables in events or methods, which are private by default, by using the PUBLIC, PRIVATE, or LOCAL commands or by adding properties to the form.

  15. Change form-level variables to user-defined form properties.

  16. Create form methods for form-specific procedures and functions.

  17. Make all data sessions private.

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.

Moving a Foundation READ into Visual FoxPro

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.

Other Gotchas

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 *

Views in Visual FoxPro

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.

Converting Tables

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.

Approach 3: Total Rewrite

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")

Summary

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