Session E-FUN

Having fun with OOP

Calvin Hsia
Microsoft Corp.




Here's your newly discovered way to make dynamically resizable forms:

Add two properties to your Application form subclass: nLastWidth and nLastHeight. Set their values to be =Thisform.Width and =Thisform.Height. When the user resizes the form, the resize event will trigger and can store/retrieve the original size from these properties.

Add another couple properties called nMinWidth and nMinHeight and set these to the desired minimum values.

Add this to your baseclass FORM RESIZE event:

Create a custom method called Dosize:

Note the special code to change the fontsize if the baseclass is a commandbutton.

The code takes advantage of the control array method of referring to container objects. ControlCount is a property of a container, and each individual control can be referenced with Control[n], where n ranges from 1 to ControlCount. For PageFrames, there is a PageCount property, and a page can be referenced with Pages[n]

Now when you create a new form based on this class, all objects on the form will resize proportionately to the form resizing:



There are two important kinds of object hierarchies to understand in Visual Foxpro. The Inheritance hierarchy is the lineage of a control. Every class along this hierarchy has the same baseclass. A commandbutton is always a commandbutton. An object has a propery called BaseClass and one called ParentClass.

The Containership hierarchy is very similar to a computer file system with subdirectories. An object's full name is indicated by the container hierarchy separated by periods, just as a full path for a filename is indicated by a series of directory names separated with a backslash. For exmample, Myform.Pageframe1.Page2.Command1 indicates the command button on Page2 of PageFrame1 on form Myform.

When an error occurs in your program code for an object, Visual Foxpro will invoke that object's error handler. If there isn't one for that object, VFP will look to see if it has inherited an Error method. If not, the ON ERROR handler is next in line followed by the default VFP error handler. For example, if you have a form with several objects on it, and an error occurs in one of those objects, the inheritance hierarchy is checked for the error handler, and not the containership hierarchy.

Often, you will want the FORM's error event to be invoked when an error occurs anywhere on the form. Add a new property to each baseclass control: lRetry. Add the following code to the ERROR event of all your subclassed VFP base class controls:

Add two properties to your baseclass FORM

In your baseclass FORM's error method, add the following code:

If you would like to trap a particular kind of error in a button's click event, you can set THISFORM.lSetErrorOff=.t. When the error handler sees this property is true, it just sets nHadError to .f.



When your user closes and reopens a form, wouldn't it be nice if your app remembered the last form size/position? Add the following two lines to your baseclass form's INIT Method.

In the Moved and Resize method, add the line:

and add a Pref method:


Another form behavior that your end users might find useful is the AlwaysOnTop pin that you find on the property sheet. With so many forms and limited form real estate, the end user can benefit from being able to set some forms to be AlwaysOnTop.

Create a new form, add a checkbox, and put in the single line of code:

Delete the Caption property, change the Style property to Graphical, and change the Picture and DownPicture properties to point to the pushpin BMPs that are in your VFP\samples\graphics directory. Run the form to test it. When you have it working, add it to your VCX by choosing SaveAsClass from the Form Designer. You can drag/drop this class from the Project manager onto any form in the form designer. If you want this to be in your base form class, you can add it to there so that all your forms will inherit this behavior.




The new MOUSE command allows you to programatically move the mouse and click. This makes it easy to create automatic testing scripts to test your applications. In the CLICK event of your subclassed VFP controls, add the following code:

Do something simple and visible to demonstrate auto testing

The #IF...#ENDIF surrounds the DEBUG code that enables the logging of events. A simple table is used to keep track of the name of the object that was clicked. The full name is used, such as Pageframe1.Page1.Appcmd2.

Run your application with this code enabled, and the output log will record your test actions. Write another program that invokes your application and runs the test script:

First, run the form and record the script

the last click is the Quit button which does a CLEAR EVENTS and


now run the form and click where the script says to click.

These several techniques are easy to add to your subclasses of the VFP baseclass controls, so that all your applications inherit new capability. Thus, don't use the VFP baseclasses directly when developing your applications.