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.

GetExpr

GETEXPR is a cool little command that allows you to bring up the Expression Builder within your application.

Usage

GETEXPR [ cPrompt ] TO cRetVal
        [ TYPE cVarType [ ; cErrorMsg ] ]
        [ DEFAULT cExpr ]

Parameter

Value

Meaning

cPrompt

Character

The message that appears within the Expression Builder as a prompt.

cVarType

Character

The variable type the Builder should verify, expressed as a single letter using the standard type abbreviations. Accepts D, L, C, I, N, T, F, Y, and B—everything but Memo, General and Picture.

cErrorMsg

Character

The text to appear in a message box if Visual FoxPro can't evaluate the supplied expression or it's not of type cVarType. The test occurs when the user chooses either Verify or OK. Note the strange syntax here: cErrorMsg must be included in the same string as cVarType, separated from it by a semicolon.

cExpr

Character

A default to be supplied to the user.

cRetVal

Character

The expression entered by the user, the default value if the user doesn't change it (whether he selects OK or Cancel), or an empty string if the user enters nothing and no default is supplied. If the return variable did not exist, it is created. If no default is specified, an empty string is returned.

The Expression Builder is called a builder, but is different from all the other builders available within Visual FoxPro. However, since this is the only builder available within a runtime application, the end users shouldn't be confused by the terminology.

The display of system memory variables at first appears to be alphabetical (_Alignment, _Box, _Indent, _LMargin) but scrolling through the list reveals a jumble with the new latest additions (including one totally blank character item) at the end. We think this list would make far more sense in alphabetical order.

The error dialog that appears with your cErrorMsg text has both OK and Help buttons; for the life of us, we couldn't find a way to bring up this function without the Help button being disabled. If they're gonna offer help, Microsoft ought to give us a ContextID to hook onto.

Note that the cVarType parameter does not control the type of the return variable—a string is always returned. If no entry is made, the string either contains the default or, if no default was supplied, is empty. You must check for an empty return before attempting to convert the variable (using VAL(), CTOD(), CTOT() or your own parsing routine) to the desired variable type.

The Expression Builder is not what we would call a graceful example of user interface design, but it is a tool that can bring much power into the hands of your more capable users. All table fields are available and system memory variables may or may not be visible.

There is no way to determine if the user hit Cancel. In this case, the default value is returned.

If the user opens any of the drop-down lists (date, math, logical or string), then presses ESC, the drop-down list closes, as you'd expect, but the highlighted value in the popup is placed in the Expression edit box, anyway.

If any change has been made to the expression in the dialog before Cancel is pressed, a confirmation dialog appears: "Discard changes to expression?" In many cases where the option to cancel is non-destructive, we find this confirmation dialog to be intrusive, but there doesn't appear to be a way to turn it off—it shows up regardless of SET CONFIRM or SET SAFETY.

The Options button allows the end user to determine which variables and expressions she wants to see, and whether aliases should or should not be included in the resulting expression. The preferences selected in the Options dialog are stored in the current resource file, with a type of “PREFW” and an Id of “GETEXPR.” Flagging this record as read-only and distributing your resource file with your application is a nice way to get a customized Expression Builder into your client’s hands. Obviously, if no resource file is available, the options selected are not preserved from one session to another.

GETEXPR is a distinctive Xbase command. Unlike most language constructs within the system, GETEXPR is designed as a command and not a function, so even though it returns a value like GETPICT() or GETDIR(), it is written in a vein similar to CALCULATE, another Xbase oldie-but-goodie.

The _GETEXPR system memory variable, added in VFP 6, provides a hook to allow a developer to create her own dialog or modify some of the behaviors of the existing one. Whenever the GETEXPR command is found, FoxPro looks to the _GETEXPR variable and runs the code specified there instead.

Although this is a pretty cool feature, it has some rules you'll want to follow. Your replacement routine must accept four parameters, matching the dialog caption, return type, error message and default of the native command. If these settings are not specified in the call, VFP provides empty strings to your routine, so you don't need to validate the type of the supplied parameters. The native GETEXPR command accepts blank strings in any of these positions just as if that option had been omitted, and you will want your routine to do the same.

Using GETEXPR within a routine that has been designated as the _GETEXPR function causes a recursive call, eventually leading to the FoxPro error "Allowed DO nesting level exceeded." If you need the native functionality, save the _GETEXPR value and restore it after invoking the command.

Example

* GE.PRG – shell around GetExpr
* To use: STORE "YourPath\GE.PRG" to _GETEXPR
* GETEXPR <your arguments>

#DEFINE CR CHR(13)

LPARAMETERS cExpressionType, cErrorMessageText, ;
   cDefaultExpression, cCaptionText

WAIT WINDOW "Expression type:   " + cExpressionType + CR + ;
     "cErrorMessageText: " + cErrorMessageText + CR + ;
     "cDefaultExpression: " + cDefaultExpression + CR + ;
     "cCaptionText: " + cCaptionText ;
     NOWAIT

LOCAL cParm2, lcGetExpr

* Here's where you can modify supplied parameters,
* choose to invoke your own custom forms, or
* default to the native functionality.

* Construct the second parameter.
cParm2 = cExpressionType + ;
         IIF(NOT EMPTY(cErrorMessageText), ;
             ";" + cErrorMessageText, "")

* This routine is the GetExpr call; store off the value.
lcGetExpr = _GETEXPR
_GETEXPR = ''

* Invoke the native GetExpr
GETEXPR cCaptionText to lcRetVal ;
        TYPE cParm2 ;
        DEFAULT cDefaultExpression

_GETEXPR = lcGetExpr
RETURN lcRetVal

See Also

Configuration Files, CToD(), CToT(), _GetExpr, Set Resource, VAL()