Subclassing Visual FoxPro Base Classes

Richard A. Schummer

Rick Schummer has been a FoxPro developer by day and night since 1989. He's also the president of the Sterling Heights Computer Club and a co-founding member of the Detroit Area Fox User Group. He enjoys camping and cycling. CompuServe 70254,1643.

This article originally appeared in the January 1996 issue of FoxTalk, published by Pinnacle Publishing Inc, PO Box 888, Kent, WA 98035-0888; 800-788-1900; 206-251-1900; http://www.pinpub.com.

To subclass or not to subclass, that's the question. When, if ever, should you use Visual FoxPro base classes directly in your applications?

At DevCon 95 and during the Visual FoxPro beta, the conventional wisdom was that developers should subclass all of Visual FoxPro's base classes. I went with the crowd at first, but then I changed course and used the Visual FoxPro-provided base classes directly. This article is about a bad decision and a learning experience that I want to pass along to the readers of this fine publication. I debated this process all during the beta and finally saw the light I was looking for.

The basics

Visual FoxPro comes with 29 base classes. These internally defined classes are provided by Microsoft and can't be modified directly. You can use these classes directly within an application, and you can subclass them. The conventional wisdom in the FoxPro community is that the base classes shouldn't be used directly in your applications. Instead, each should be subclassed, and you should use those subclasses (and other subclasses derived from them) in your applications (see Table 1). This will allow you to customize and standardize each class to have the functionality, look, and feel that you prefer. All the changes made to the subclassed base classes are then propagated throughout your applications using the power of inheritance.

Table 1. Visual FoxPro base classes and standard name prefixes.

Base Class Naming Prefix
CheckBox chk
Column * grc
ComboBox cbo
CommandButton cmd
CommandGroup cmg
Container cnt
Control ctl
Custom  
EditBox edt
Form frm
FormSet frs
Grid grd
Header * grh
Image img
Label lbl
Line lin
ListBox lst
OLEBoundControl olb
OLEContainerControl ole
OptionButton * opt
OptionGroup opg
Page * pag
PageFrame pgf
Separator * sep
Shape shp
Spinner spn
TextBox txt
Timer tmr
ToolBar tbr


* These classes can't be subclassed in the Class Designer because they belong to a parent container.

[There are also undocumented base classes that can be subclassed only programmatically with DEFINE CLASS: DataEnvironment, Cursor, and Relation.—Ed.]

There are definitely some things you'll want all of a specific object type to do that Microsoft didn't default to or provide. This is your chance to customize the different properties, events, and methods in the classes. One example is to base all the TextBox objects in an application on your personal TextBox base class. Microsoft set the default the text color to black. If you want all TextBox objects on every form you create to have a blue foreground color, it's as simple as setting the ForeColor property to blue using Visual FoxPro's property sheet and color picker to modify your personalized base class. The inheritance built into Visual FoxPro will propagate the change to every TextBox object based on your TextBox class to blue. Another example might be to change the FontName or FontSize properties so all your form objects are consistent within an application (provided you don't break inheritance).

The New Class dialog box is very straight forward. Fill in the name of your new class. The "Based On:" combo box is where you select the parent class to your personalized base class. The combo box drop-down list contains each of the Visual FoxPro base classes that can subclassed visually. Finally, type in the Visual Class Library filename or use the ellipse button to select an existing library. I recommend keeping all your personalized base classes in one Visual Class Library. Once you complete the dialog box, the Class Designer is started so you can modify your new class. Use the property sheet to alter any properties, events, or methods to your personal specification. This is very easy to do (don't worry, I won't tell your customers or the boss). I think it took me no more than five to 10 minutes initially to set up my current set of personalized "base" classes.

How to subclass the base classes

There are several ways to create a personalized set of base classes. I prefer to create them using the Visual Class Designer. Begin by typing the following in the Command window:


 CREATE CLASS

You can also choose New from the File menu or the New icon on the standard toolbar to get the New File dialog box. Then select the Class option button and the New File command button to bring up the New Class dialog box (see Figure 1).

Figure 1. New Class dialog box.

Drag and drop is lost

There is a downside to subclassing the base classes. One of the most frequently demonstrated and talked about features at DevCon 95 was drag and drop. You can quickly set up a form's data environment by adding tables from a database container or from free tables. You can then drag and drop fields from the tables in the data environment to the form. The newly added objects on the form will take the default base class for the field data type. Most fields default to the TextBox base class. Logical fields will default to the CheckBox base class, and memo fields will default to the EditBox base class. If you drag the table on to a form, you'll get a grid base class object. This is extremely slick and works as advertised.

If you set up your own "base" classes (a visual class library of subclassed base classes), Visual FoxPro won't know to default these dragged objects to your own classes. Unfortunately, there's no way to get these objects to use your base classes without some customized Builder or Wizard. Such a routine would be fairly difficult to write, because it would have to actually change the class of the objects dropped, which would—as far as I know—require operating directly on the .SCX file outside of the Form Designer. This would make seamless integration with the development environment difficult to achieve. This seems like a lot of work to me. I've spent enough time learning the basics of this product; I don't want to start writing utilities to change base class properties. I'm sure some developer will eventually come up with the solution, but I don't want to wait.

So the choice is as simple as "drag and drop or customized base classes." It's an unfair choice, but one I think each developer will need to make at some point early in their Visual FoxPro apprenticeship.

[Here's something to think about that might make the decision easier: since a data environment can be associated only with a form, saving a form as a class causes you to loose its data environment. In other words, data environments can't be visually subclassed, so you have to set one up for each individual form you create. Some developers feel this is enough of a liability that they are willing to forego the visual data environment designer altogether. Instead, they create DataEnvironment container classes programmatically, attaching code to each form's Load or Init events to manually instantiate the appropriate DataEnvironment object for the form. If you buy into this argument, then subclassing becomes almost a "no-brainer," since with this approach you can't drag and drop fields from the data environment anyway.—Ed.]

A solution finally realized

I talked with several developers about this during the Visual FoxPro beta. The debates never led to a clear solution or reason to go one way or the other. It wasn't until I started developing some "production" screens that I finally realized why I wanted to create my own base classes. The reasons were two-fold (and in order of importance):

Microsoft defaults for properties and methods. I don't think every developer will agree on every default that Microsoft came up with for every property and method. I know I've changed a few basic properties. I've also added a few properties of my own, and I'm sure a method or two will be added over time as well. This is where the real power is.

Naming conventions. I was tired of each new object added to the form having names like Label1 or TextBox1. This required me to change the name to lblAddress or txtAddress in order to conform to Microsoft-recommended naming standards. I solved this by naming each of my base classes to conform to the Microsoft naming convention. For example, my base class TextBox is called txtTextBox. All I had to do is substitute "txtTextbox" for Microsoft's default name, "TextBox1." At design time, this results in TextBox names defaulting to txtTextBox1, txtTextBox2, and so on, a significant time savings. I also don't need to look up the standards in the help file when I forget them.

Using your personalized base classes

The classes are easy to create, but you might be asking "how easy are they to use?" Fortunately the Microsoft FoxPro team made using Visual Class Libraries as easy as they are to create. There is a View Classes icon (it looks like some books on a shelf) on the Form Controls toolbar. This brings up a pop-up menu. Choose the Add menu option to add your personalized visual class library to the menu, then choose your library from the menu. The toolbar will change to reflect your base classes.

You can set up Visual FoxPro to pre-load the View Classes menu with customized visual class libraries. Do this by using the Controls page of Visual FoxPro's Options dialog box (choose Options from the Tools menu; see Figure 2).

Figure 2. Adding visual classes to the View Classes menu.

Basic base class modifications

I have made some basic modifications to my personalized base classes. The BackStyle property of Labels and CheckBoxes defaults to "0 - Opaque," which will drive you nuts if you've moved to a form color other than white. I've modified the BackStyle property of my Label and CheckBox base classes to "1 - Transparent." I don't really understand Microsoft's thinking on this one, but thankfully we have simple ways to make these changes.

Another change that I find even more critical is my "base" class for Forms (called frmForm). This is my form Template Class that is set on the Form page of Visual FoxPro's Option dialog box (see Figure 3). Each new form created is based on (or, if you prefer, "inherits from") my template form class instead of the built-in Form class. This way, as I develop my forms and come up with my application development methodology, all I have to do is make changes in one place. If I add a custom property or method, each existing form based on my template form class automatically inherits the new value or functionality. [If you use FormSets, you might also want to create a template FormSet class. For detailed information on how form and FormSet templates interact, see the topic, "Using Form and Form Set Templates" in Visual FoxPro's help file.—Ed.]

Figure 3. Setting the template form.

Conclusion

I decided that the "modify once, propagate everywhere" philosophy is the way to go. Losing drag and drop functionality was a small price to pay. I now add objects one at a time to my forms. I add an object, make any changes I need, and copy the first object over and over. For example, I'll add a TextBox object to my form and modify the appropriate properties. I then copy that object to the Clipboard and paste it on the form when I need another TextBox object. This procedure saves me time in the long run.

Another concern I have with personalized base classes is adding another "layer" in the class hierarchy. I haven't performed, nor have I seen, an analysis of how this impacts runtime performance. Theoretically, it should slow performance slightly because Visual FoxPro has another layer to traverse as it looks for property values and to execute methods. [FoxTalk is preparing an article with benchmarks on this topic.—Ed.]

I hope this article has provided some insight on a topic that will be debated over and over as Visual FoxPro developers learn more about this exciting product. If it saves you time in making a decision or provides you with more arguments for going one way or another, then I've accomplished what I set out to do.

On this month's Companion Disk I've provided the visual class library VF3BASEC, which contains all of the subclassed base classes that I use in my applications.

To find out more about FoxTalk and Pinnacle Publishing, visit their website at
http://www.pinppub.com/foxtalk/.

Note: This is not a Microsoft Corporation website.
Microsoft is not responsible for its content.

This article is reproduced from the January 1996 issue of FoxTalk. Copyright 1995, by Pinnacle Publishing, Inc., unless otherwise noted. All rights are reserved. FoxTalk is an independently produced publication of Pinnacle Publishing, Inc. No part of this article may be used or reproduced in any fashion (except in brief quotations used in critical articles and reviews) without prior consent of Pinnacle Publishing, Inc. To contact Pinnacle Publishing, Inc., please call (800)788-1900 or (206)251-1900.