Logo

Hacker’s Guide to Visual FoxPro
An irreverent look at how Visual FoxPro really works. Tells you the inside scoop on every command, function, property, event and method of Visual FoxPro.

ReadExpression, WriteExpression, ReadMethod, WriteMethod

These are the methods that make builders and wizards possible. ReadExpression and WriteExpression give you access to properties containing expressions (as opposed to values). ReadMethod and WriteMethod let you access and change method code.

Usage

cPropExpression = oObject.ReadExpression( cProperty )
lSuccess = oObject.WriteExpression( cProperty, cPropExpression )
cCode = oObject.ReadMethod( cMethod )
lSuccess = oObject.WriteMethod( cMethod, cCode [, lCreateIt ] )

Parameter

Value

Meaning

cProperty

Character

The name of the property whose expression is being accessed or changed.

cPropExpression

Character

An expression beginning with "=" that is assigned to cProperty. The expression is not evaluated in the WriteExpression call, but is stored to the property for evaluation at runtime.

cMethod

Character

The name of the method whose code is being accessed or changed.

cCode

Character

The code for cMethod. Lines are delimited with CHR(13).

lCreateIt

.T.

cMethod should be created if it doesn't exist.

.F. or omitted

An error occurs if cMethod doesn't exist.

lSuccess

Logical

Indicates whether the change was successful.

In VFP 3, all of these methods are available only at design-time. In VFP 5 and later, ReadExpression, WriteExpression and ReadMethod are available at runtime as well.

ReadExpression and ReadMethod return what they find in the specified property or method. WriteExpression and WriteMethod return .T. if they’re successful. As far as we can tell, they never actually return .F. because they trigger errors instead.

ReadMethod and WriteMethod are pretty straightforward. They simply let you grab the code that’s already in a method or put new code there. Be aware that WriteMethod overwrites any existing code. To add to what’s already there, grab it first with ReadMethod and then concatenate the new code onto the end. WriteMethod got a little more capable in VFP 7, with the ability to create a new method on the fly.

The property-related methods are a little more confusing. What’s going on here is that they’re meant for properties containing expressions rather than values. If Caption is “My Great Form,” you can find that out without ReadExpression. But if Caption is set to = “My Form - “ + MDY(DATE()), you need ReadExpression to find it out. If you just look at Caption, you’ll see something like “My Form - September 28, 2001”—not what you want to know.

Similarly, if you want to store an expression to a property, you can’t just write the assignment. If you set Caption to “My Form - “ + MDY(DATE()), the expression gets evaluated immediately and the result is stored in Caption. Again, not what you want. WriteExpression lets you store the expression itself, so it can be evaluated at runtime.

With the AddProperty method that was added in VFP 6, we suspect WriteExpression will be more useful than ever, since we can now create properties that can’t be set up at design-time, so we’ll have more need to store expressions in properties at runtime.

You need to call these methods for the object you actually want to change. You can’t pass a name that drills down into the object hierarchy (like “Form1.Grid1.Column1.BackColor”) for cProperty or cMethod—you have to pass something like “BackColor” or “Click”. At design-time, you get your hands on the object you want by calling ASELOBJ() or SYS(1270).

Because you’re dealing with strings here and they might need quotes inside, this is one place where having three sets of character delimiters really comes in handy. We’ve used all three (“”, ‘’, []) in a WriteExpression call.

In some versions, munging up the expression by skipping or mismatching a pair of string delimiters returns the informative "Unknown error code: " followed by a negative number. If you see this, try reworking your expression; something in there is confusing FoxPro. This bug was fixed in one of the service packs for VFP 6.

You’ll find more information on these methods in “Builders and Wizards (and Bears, Oh My!)”.

Example

* Set a form's caption to include today's date.
* Get a reference with aSelObj().
= aSelObj(aSelect, 1)
* Now assign the property:
aSelect[1].WriteExpression("Caption", ;
   '= "My Form - " + MDY(DATE())')

* Set the DynamicForeColor property of a grid column.
* First we put a reference to the grid in aSelect[1].
* Make sure the grid is selected, then:
= aSelObj(aSelect)
* Now we can work with it.
aSelect[1].Column1.WriteExpression("DynamicForeColor", ;
   '= "IIF(balance<0, RGB(255,0,0), RGB(0,0,0)"')

* Hmm, maybe we want all columns to have that. Let's
* set the grid's Init to do it for all columns, but we
* don't want to lose anything already in the Init.
cInitCode = aSelect[1].ReadMethod("Init")
aSelect[1].WriteMethod("Init", cInitCode + CHR(13) + ;
   [This.SetAll("DynamicForeColor", ;
   "IIF(balance<0, RGB(255,0,0), RGB(0,0,0))")])

See Also

AddProperty, ASelObj(), Sys(1270)