The Way Things Work

Parameters

BUILDER.APP accepts parameters from the product, and any substitute for BUILDER.APP needs to have a parameter statement as its first line of executable code to avoid an error. As of this writing, the first parameter to the product sends to the BUILDER.APP, a reference to the selected object on the form being designed. This may change by the time the product is shipped. If multiple controls on the form are selected, the product will not create an array of these objects but pass in the array as the first parameter. If this occurs, the value of this first parameter will simply be a reference to the object that FoxPro considers to be the first object in the group, i.e., the object that would have occupied the first array element if an array had been created. To handle these issues, BUILDER.APP gets references to selected objects directly (this method is discussed later), any substitute Builder program should do the same thing.

FoxPro also passes in a parameter indicating the origin of the call to BUILDER.APP. From the button on the Properties sheet, the value of this parameter will be Psheet. If Builders are called from the Alternate Mouse menu, its value will be Rmouse. If the Builder Lock button is down and you drop a new control onto the form, the parameter's value will be Toolbar. Finally, if the Form Builder button is pressed, its value will be Qform.

This parameter allows you to write Builders that are somewhat context-sensitive. For example, if you want your Builder to behave differently for the new controls than the existing controls, a parameter value of Toolbar will tell you that this is a new control that has just been dropped onto the form. Such a Builder might, for instance, apply a standard set of default settings automatically to the new control and return you to the Form Designer—with no user interface presented at all—while existing controls would not get their settings overwritten with such defaults, but instead would get the Builder's UI to allow them to adjust the current property settings.

Directly Invoking Builders

Knowing these parameters, you don't need to rely on the product's hooks to call the program identified by _Builder. You can invoke your Builder program at any time by issuing the command:


DO (_Builder) WITH <some list of parameters>

If you substitute your own program for BUILDER.APP, you don't have to send any parameters if you call it directly. However, the product's hooks will always be sending some parameters, so your Builder program should handle these with a parameters statement, and then it can ignore them if you wish.

Should you substitute your own program for BUILDER.APP? There may be advantages for you to do so, but you should think through the issues carefully and determine if it's really worth it. For most developers, we suspect that the place to put your energy is in creating and registering custom Builders, and using the default BUILDER.APP to find and run these.

Finding the Selected Object(s)

One thing any BUILDER.APP will probably want to do is to get references to one or more selected objects on the form being designed. If you have a reference to some object—selected or not—and you write a replacement for BUILDER.APP appropriately, your program can do whatever it wants to that object. Most of the time, the user will be working in the Form Designer, will have selected one or more controls, and will have invoked the Builder program in order to get help building the selected object(s).

A new function in FoxPro, ASELOBJ() returns references to selected objects. A call to ASELOBJ(x) will create a one-dimensional array called "x," which will contain an object reference for each object currently selected on the form. If only one object is selected, your array will contain just the one element, and you can reference the object as "x[1]."

ASELOBJ() also takes optional numeric arguments. ASELOBJ(x,1) will give you a reference to the object that the selected control is sitting on. ASELOBJ(x,2) will provide the name of the form's Data Environment object. Each of these variants of ASELOBJ will place the object references into the designated array, just like the usual ASELOBJ(x) call.

Updating the Underlying Controls

When your Builder wants to update a property of the underlying control, use its object reference. In the example above, to change the Caption property of the selected control to OK, your code would say:


x[1].Caption = "OK"

When you do this from within your Builder, the caption on the underlying selected control immediately change to the new value.

To avoid having too many windows on the screen at a given time, particularly at lower resolutions, and because the shipping Builders are modal, BUILDER.APP hides the Properties window (Hide Window Properties) while the Builders execute. The Properties window is getting the new values as the Builder changes them, so in this example, the Caption property as listed in the Properties window has a value of OK as well.