FoxSpoken Volume 1
Most Recent Volume, Fox Stuff
Other Retired Fox Volumes
articles on this page retired Apr.97
Before you use this material, please be sure you have read and understand
the various provisos *3 with which
I provide it for your use.
Contents of this page:
- Class Browser add-on for #INCLUDE files
- PARSER: ways to parse and execute code
- The Whipped Tip Dept: Editor Comment Strings
- CLASSDOC: class-dependency diagramming utility
- Grid Partitions? Please... Just say no
- AppWiz: a place to start your frame-work?
GENMENUL.PRG and AUTOVER
Pertinent files: GENMENUL.ZIP updated Jan.97, ~25k.
A separate text file, GENMENUL.TXT ~4k, is
available if you want more information about AUTOVER/GENMENU before
downloading. This text file is included in the .ZIP.
Rejoice. Microsoft have uploaded a replacement GENMENU file,
improved over the version of GENMENU that shipped with 5.0
it out on the MS site).
The new version eliminates a number of bugs, especially some that affect
top form menus. Ever try to figure out why your top form menus don't Append
as they should? Or why they behave so badly with multiple top form menus?
Or why your system pads sometimes deliver 'blank popups' after you use
a top form menu? Or why your Setup and Cleanup didn't get generated properly?
The new GENMENU -- and the more flexible arguments you can use when you
DO the.MPR -- will help you out. You'll want to study the comments at the
top of an .MPR, to understand how to call the new-style MPRs with extra
MC Framework people and others have been using my hacked version of
GENMENU, GENMENUL, for some time. At various stages GENMENUL has included
quite a few improvements over the standard GENMENU -- I think the MAChete
book had the most elaborate version -- but at this stage GENMENUL for 5.0
includes only one addition that we've found critical to development.
This is AUTOVER, a technique pioneered by
Peirse. AUTOVER forces certain extra processing to take place during
every project build by using a special, self-editing menu.
As its name suggests, the original purpose of AUTOVER in Matt's version
was to force the Project Build process to auto-increment an application
build number. My version allows you to add any additional BUILD APP processing
you'd like to the special menu, but the build-numbering is the one extra
GENMENU feature that we couldn't live without. Naturally, MC Framework is
'AUTOVER-aware', and makes good use of your build information if you make
an AUTOVER-type menu available to an MC controller object.
MC doesn't mandate GENMENUL or AUTOVER use. However, the next MC upload
will include code that assumes the new GENMENU you can get from
Microsoft or the new GENMENUL you can download here. That's because
a good many of the current MC changes will be topform-related; the new
GENMENU means I can remove some of the worst MC workarounds, in the form
classes as well as the MC template menus, and plan a better topform strategy
Whether you use MC or not, you owe it to yourselves to download one
of the new GENMENUs, and you have no reason to wait!
By request, and with permission from >L< and Matt,
Ross MacNeill added AUTOVER and several other
menu techniques to his groundbreaking GENMENUX program in the 2.6-3.0 time
period. (Check out the SKIP_REDIRECT generator directive, for example.)
I'll probably add these back into GENMENUL when I have time, but no promises.
If you're a GENMENUX user, you'll want to check with Andrew to see if he's
updated GENMENUX for the topform changes.
Class Browser Add-On for #INCLUDE files
Pertinent files: ADDINCL.ZIP updated Apr.97 to fix bug with
member objects, ~10k.
A text file from this .ZIP, ADDINCL.TXT ~3k, is
also available for viewing before download if you wish.
If you've never written an AddOn for the Class Browser, you might want
this file just to see how you might create and install such a thing.
If you've ever changed a .H (header) filename or location, and then
cursed because you realized that you were going to have to edit a bunch
of classes to know where their Include Files were, now you can do this
through the Class Browser interface.
BTW, I don't know if it is still a problem in 5.0, but you could run
into major problems in 3.0 if you tried to save changes in the Class Designer
or Form Designer for a class whose Include File was open in Notepad someplace.
If you've had GPFs when saving a class and don't know why, this could be
the reason: Fox tries to do the compile, et voilà.
PARSER: parsing and executing code at runtime
Pertinent file: PARSER.TXT, ~3k, is all you
need. I've placed it here in text form so you can refer to the limited
code while you read this page, but, once downloaded, you only need to
rename it to a PRG to have runnable code.
This keeps coming up on line: How can I create new lines of code dynamically
at runtime, and then execute them?
There are two main ways this can be done:
- You can place all the lines of code into a PRG on disk, which can
be compiled and executed like any other program, or
- You can macro-expand the code, line by line, for execution.
The first method is generally a better choice, IMHO. It's fast, because
it makes Fox do all the work. You don't have to struggle with evaluation
of structures and conditional logic which should force lines to be omitted
or repeated. (There are quite a number of such constructs in VFP.) You can
add separate procedures as necessary.
Think about it: this is how a lot of your internal Fox work is getting done,
and how much of the work your Inet applets, MS Office, and half the rest of
the world do their work too. A temporary file is created and then things
happen to it. The application that creates the temporary file has several
responsibilities, such as keeping track of a unique name for this file,
deciding on a reasonable location for it, and cleaning it up when work is
Incidentally, for the purposes of appropriate file cleanup, you may be
interested to know that the Fox ERASE command is NORECYCLE by default. This
keyword is undocumented, but may still be added to your ERASE command line,
to emphasize the fact that the ERASEd file will not be placed in your Recycle
Bin. The opposite keyword, RECYCLE, which is documented, will place
ERASEd documents into the Trash, er, Recycle Bin when appropriate.
If you download GENMENUL.PRG, you'll have a perfect
example of this technique, including appropriate error-handling. (Look at the
code I added in the BuildEnable() procedure, which runs code in
the Comments field of a special MNX record.) In GENMENUL, I'm working from a
memo field, but your code could be TEXTMERGEd directly to a PRG at runtime,
or the PRG could be created in many other ways.
I am not sure why people think that creation of a temporary file and running
it in this manner is a bad idea. The only down-side I can imagine is that
you can't use it under the runtime libraries. The most significant difference
between the full product and a distributed application that runs under the
runtime libraries is that the latter cannot compile code.
If you need to use your dynamic code-creation-and-execution method under the
runtime, you're stuck with the second method: parsing and macro-expanding code,
which does not require compilation. PARSER shows you how I do that.
PARSER is unusual in that it puts all the code into an array of lines,
RETURNing this array to a calling program that passed the array by reference.
(In other ways, PARSER may only be 'unusual' in a little extra niceness
of attention to concatenation and comment types -- does anybody really use
I use this method because the outer program can then look at the results and
decide whether further evaluation is required. For example, the outer program
would be responsible for handling loops' duration and scope, if you need such
I don't really require dynamically-created code that includes
loops, but my sample call for PARSER, shown as notes at the end of the file,
gives you another reason I do require some extra evaluation outside PARSER.
If you feel sure nothing like this could ever happen to you, feel free to adapt PARSER
to execute each line of code as it parses the line rather than passing the array.
If you need to parse text strings for this use or for any
other reason in Fox, you should take particularly note of the _MLINE
system variable used in this code, probably the most generally valuable
part of this example. _MLINE is a system-maintained offset that can
significantly speed up your work parsing large text strings.
The Whipped Tip Dept: Editor Comment Strings
I try to be ladylike, really I do. And I SWORE (in a very ladylike manner,
naturally) that I was not going to publish trivial Fox tips on
my site, I don't have room or time. But sometimes you just gotta:
The January 97 issue of DBA -- which I note in passing also makes the
Pollyannish statement that you 'only need to know a few things to
quickly publish databases on the Web' <sigh> -- contains Tamar Granor's
piece describing the VFP 5 improvements over 3.0.
I recommend that everyone familiarise his or her self with the differences
between the releases, and this article is certainly one place you could start.
However, Dr. Granor suggests that 'control over the... comment strings'
would be an 'extremely useful enhancement'. She'd be absolutely correct,
except that it's already in the product! I suppose if we emended her statement
to say that 'control available through the standard UI' would be 'a small
enhancment', it would be correct -- but the functionality you want and
need, which is the main event, is IN THE PRODUCT, folks, so don't
get the wrong idea.
Here's how real Fox programmers can take control of their comment strings,
until such time as the 'small and relatively trivial enhancement' of a
Tools Options dialog entry (or whatever) is available:
Not surprisingly, you edit the Windows Registry (use REGEDIT).
The key you want is:
You probably won't find it in there by default; I had to add it. Use
the comment string you want as the value data for this key, obviously.
Anybody at the opening session at the October Fox DevCon would have known
this was possible, since this little feature was very much in evidence
during Calvin's demo. I don't know what DBA's lead time is, to be
fair, but I think this key went into the registry fairly early in the 5.0
beta. I'm sure you're going to want to start using it before the next release <g>.
The Teaching Your Grandma To Suck Eggs Dept
Pertinent files:CLASSDOC.ZIP updated Jan.97, ~13k
If you wish some additional information about CLASSDOC before download, you
can read CLASSDOC.TXT ~11k, a text file from the
.ZIP -- but as you see it's almost as big as the .ZIP file!
In much the same vein as The Whipped Tip, somebody on
(check out the msnews.microsoft.com news server*2)
recently decided to explain what recursion was to me <sigh>.
I'm uploading CLASSDOC partly to correct any impression that may have
resulted from this discussion, and partly to give wider exposure to a
tool I've written that (I feel) provides a truly useful example of
recursion. It also uses the treeview control -- another item that
seems to give people fits -- and provides a good use of the
common dialog control, plus some insight into the VCX structure
and a bunch of other important techniques.
CLASSDOC was written for one of my private clients, who has graciously
consented to my sharing it with you. They needed to explore the dependencies
between classes, in a very large class tree. The Class Browser doesn't fit
this requirement, because it lets you look at a class' own superclasses,
which determine its own inheritance, but can't help you resolve what
effects editing a parent class might have on its multitude of
Looking at the classes within one project doesn't help, either, since your
library classes may be used by a multitude of projects. You'll want to
know what effects any change will have on all of them.
So CLASSDOC asks you to determine a "baseclass library". This is the VCX
that contains the classes you may want to edit. CLASSDOC will then check
the VCXs in the same folder, and as many other folders as you would like
to add, for other classes that depend on your chosen "baseclass VCX".
The current CLASSDOC family of classes provides its output in five formats,
which include some different levels of detail. To help you organise the
current set of options into preferences, the single CLASSDOC.PRG starts
with a set of #DEFINEs. To help you see all the different format/output types,
CLASSDOC.PRG provides a silly sample program that allows you to choose between
the five types every time you run the program (be sure to read the comments so
you can turn this off when you're more familiar with the choices), if you
continue to use my framing program at all.
You'll note that one of the options available to CLASSDOC is an "add-on" feature,
and I've supplied you with a sample (CLASSADD.PRG will give you a count of classes
in the VCXs that have been examined and don't inherit from any of the classes
in the chosen BASECLASS.VCX).
All of this, and quite a bit more, is contained in the comments and text file
that accompany CLASSDOC.PRG. You'll also find information about changes
I'd like to make to this class family in the future.
To return to the subject of recursion, it is possible to have corrupted VCX
records with empty objname fields. You'll know if this happens because you'll
run out of levels in the current program stack -- the recursion will continue
endlessly -- and CLASSDOC will terminate abnormally when this happens.
Don't worry about this before it happens (for one thing, there are some
records in the VCX that are supposed to have empty objname fields, and
they don't cause any problems in CLASSDOC). I'll include some instructions in
CLASSDOC.TXT for appropriate cleanup, in case it does happen to you.
The important thing to realise is that VFP's current stack limit (128 nested
procedural calls and 384 nested programming structures) is magnificently
capable of handling CLASSDOC's requirements. (If your class tree is nested
greater than 128 classes deep, something is terribly wrong with your
class design <g>.) In fact, I asked the gentleman who lectured me
on recursion exactly when he would need a greater limit, and I'm still
waiting for an answer <s>.
Grid Partitions: Just Say No
Pertinent files:GRIDLOCK.ZIP updated Jan.97, ~4k
The .ZIP file contains a sample form and data -- I don't think you need any
additional descriptive information beyond what I've written here.
People keep wondering why partitions don't work as expected in Grids.
The short answer is that they didn't work right in BROWSE, either.
Clue #1: Don't make the mistake of thinking that there are more separate
pieces inside the two-panel grid object than there actually are.
Clue #2: What you really want is BROWSE... LOCK, which hasn't worked
right since FoxBase. FoxPro 1.0 faked it in an attempt to remain compatible
with DBase III and keep it in the language, along with BROWSE FORMAT, but
that's another story.
If you've already had the problem, you know what I am talking about,
so I don't need to go into further detail. If you haven't had the problem,
it's because your interface requirements are sensible and don't lead you to
have any great need for Grid partitions, so (trust me on this) you really
don't want to know. Skip to the next section.
The solutions are as difficult to describe without visual aids as the
problem is to visualise unless you've had it. So, if you do need this
functionality, I've created a little sample to show you how I'd fake it.
All the really meaningful code is in the AfterRowColChange() method of
the grid -- you'll see the trick there and in the DataEnvironment.
The only other code is in the editbox's Keypress(), where I made
the Ctrl-Up and Ctrl-Down arrows scroll you through the grid, since
the grid itself is actually using memo fields and won't scroll properly.
If your 'GRID LOCK' situation really used something other than memo
fields for the 'LOCKed' field, you wouldn't have to bother with this;
you would just scroll through the grid normally using arrow keys. If your
LOCKed field really is a memo field, you could take a cue from this Keypress()
code to design a more thorough set of navigation keys.
Scroll bars on the grid have unrelated problems, and cause
ifficulties here that are REALLY NOT MY FAULT <g>, so I
didn't provide scroll bars in this example grid. If you want
scrollbars on this type of grid I would suggest an OCX, either
between the two grid 'panels' or to one side. (After all,
PanelLink = .F. doesn't really make any sense! And never did.
So there would never really be a need for two vertical scroll bars
to move the unlinked panels separately.)
A Poor Man's Alternative to Framework Use
You never use Wizards? You haven't checked out the Application Wizard
in 5.0? I think you should.
Although I wouldn't use the files it generates as they stand, they are
quite amenable to reasonable adaptation because, with all their faults,
and limitations as written, they are predicated on sound OO and Fox dev
principles. (Translation: This is not your father's TasTrade.)
What's more, you can change the template files from which the Application
Wizard generates your application files to suit yourself -- with little
effort. I mean, the Wizard makes these files available to you, and it won't
take much effort for you to figure out how to get the Wizard to use your
versions. I also mean that the template files are clearly-enough written
that you shouldn't have much trouble figuring out how they work or what
their components do. I don't mean that all the modifications I think
you should make will jump right out at you -- sorry, folks, I have to keep
some information to myself occasionally -- but you'll probably have your
own ideas on this score, anyway.
App Wiz (I just love saying that!) doesn't show up on the Wizards
list under the Tools menu. You have to choose 'All' and pick the Application
Wizard from the resulting dialog <sigh>.
Lisa Slater Nicholls