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.
These Database Events
fire when the DBGetProp()
and DBSetProp()
functions are used.
PROCEDURE DBC_BeforeDBGetProp( cName, cType, cProperty )
PROCEDURE DBC_AfterDBGetProp( cName, cType, cProperty )
PROCEDURE DBC_BeforeDBSetProp( cName, cType, cProperty,
ePropertyValue )
PROCEDURE DBC_AfterDBSetProp( cName, cType, cProperty,
ePropertyValue )
Parameter |
Value |
Meaning |
cName |
Character |
The name of the object in the database. |
cType |
Character |
The object type: DATABASE, TABLE, VIEW, FIELD, or CONNECTION. |
cProperty |
Character |
The property being read or changed. |
ePropertyValue |
Character, Numeric, or Logical |
The new value for the property. |
You can prevent the property from being read or changed by returning .F. in the Before events (in which case, the DBGetProp()
and DBSetProp()
functions return .NULL.). The After events simply receive notification that DBGetProp()
and DBSetProp()
were used.
One use of BeforeDBSetProp is to prevent someone from turning off Database Events
, therefore bypassing all the security and other things you’ve implemented Database Events
for. The first example below demonstrates this.
Another use might be to return different values than are actually stored in the DBC. Say, for example, you want to store captions for fields in different languages, and then at runtime, display the caption for a field in the user’s selected language. You might think you could use code like the following in the BeforeDBGetProp event:
IF UPPER(cType) = "FIELD" AND UPPER(cProperty) = "CAPTION"
* Look up the caption for the specified field in a captions table.
* oUser is a global user object and cLanguage is their selected language.
lcCaption = GetFieldCaption(cName, oUser.cLanguage)
RETURN lcCaption
ELSE
* Handle any other cases.
ENDIF
Unfortunately, this won’t work, because Database Events
can’t return values back to the function that resulted in them being fired; they can only return .T. or .F. (in the case of Before events) to indicate that whatever fired them can continue.
Instead, in BeforeDBGetProp, look up the desired value and use DBSetProp()
to change the property to that value, so that’s what the function will return to the caller. In AfterDBGetProp, change the property back to its former value. Thanks to Ted for pointing out this cool solution.
A field name is passed without an alias to the cName parameter. |
* Prevent someone from turning off database events.
PROCEDURE DBC_BeforeDBSetProp(cName, cType, cProperty, ;
ePropertyValue)
RETURN NOT (UPPER(cName) == UPPER(JUSTSTEM(dbc())) AND ;
UPPER(cType) = "DATABASE" AND ;
INLIST(UPPER(cProperty), "DBCEVENTS", "DBCEVENTFILE"))
* Return your own custom string rather than the underlying
* property.
PROCEDURE DBC_BeforeDBGetProp(cName, cType, cProperty)
IF UPPER(cName) = "COMPANY" AND ;
UPPER(cType) = "FIELD" AND ;
UPPER(cProperty) = "CAPTION"
DBSETPROP("Customer.Company", "Field", "Caption", "Nom")
ENDIF
PROCEDURE DBC_AfterDBGetProp(cName, cType, cProperty)
IF UPPER(cName) = "COMPANY" AND ;
UPPER(cType) = "FIELD" AND ;
UPPER(cProperty) = "CAPTION"
DBSETPROP("Customer.Company", "Field", "Caption", "Name")
ENDIF