4 |
The LA Fox Developer Newsletter
February 1997
The Nasty Secret Behind
#INCLUDE Nesting in VFP3.Ob
by Marc Deric, Laguna Groupware, Inc.
Through my interminable tinkering with Codebook and the HotLink
web stuff, I came across a problem with #INCLUDE nesting that
cost me a few hours of consternation and didn’t appear to be in
the documentation, on the MS Knowledge base, or in the online
help. I hope this article helps you avoid the same problem and
gives you a look at some of Codebook’s clever tricks (which you
might adopt even if you’re not a Codebook developer).
The cut to the chase is that VFP3.Ob only appears to support 4
levels of include file nesting and Codebook uses them all. When
you execute Codebook’s QSTART.APP, which creates the frame-
work of a new project in the destination directory of your choice,
an include file hierarchy is created for the application. The project
home directory is different from the Codebook
CDBK3O\COMMON3O directory, the latter contains all the
framework’s standard class libraries, graphics, programs, utility
APPs, and include files. The project home directory contains the
application-specific class libraries, graphics, programs, and an
application-specific include file. APPINCL.H, which contains #DE-
FINE constants for, among other things, the title of the main win-
dow Lscreen.Caption) and the name of the application’s top-level
class.
Since any specific class in library can only have one include file
(which shows in the “Reserved8” memo field if you open the .VCX
as a table) it is important for APPINCL.H itself to contain #lN-
CLUDE references to the framework’s standard include files. This
way, the application-specific classes can have access to both the
application’s #DEFINEs as well as to the #DEFINEs in the
framework’s standard include files. The astute reader might note
that this is only two levels
—
no problem’
WelI...the framework’s standard include files are themselves a
two level system. There is a file called FRAMEWRK.H which
includes some #DEFINEs and #INCLUDE references to
STRINGS.H and ERRORS.H, two Codebook files, and to
FOXPRO.H, the standard include file that comes with VFP. If you
consider the framework’s standard class libraries which use
FRAMEWRK.H as their #INCLUDEd file, it is easy to see the
motivation of
two
levels, access to framework level constants and
access to FoxPro standard constants. And we’re up to three
levels.
But what about standard classes in the framework, under the
CDBK3O\COMMON3O directory, which need to access applica-
tion-specific constants? An example is the CMainMenu class in
the CTMENUS.VCX library. This class creates the application’s
Main Menu and is programmed to install a “Utilities” menu pad for
debugging based on some application-specific debug mode con-
stants in APPINCL.H. Since this is a standard framework class
and not an application-specific class, we cannot simply include
the APPINCL.H file. Which one would we use? There are as
many APPINCL.H files on our disk as we have active Codebook
projects. For these classes, the authors of Codebook offer a
FRAMINCL.H header file. Its only statement is as follows:
#INCLUDE 'INCLUDE\APPLINCL.H'
This works because, at compile time when the header files are
used, the relative reference ‘INCLUDE\APPINCL.H’ points to thE
correct APPINCL.H file. [Aside: There is an interesting phenom-
enon which derives from this choice of implementation. The com-
piled class code for “standard” framework classes usinç
FRAMINCL.H has been created using the APPINCL.H file frorr
one specific project, the last one in which you compiled. Wher
you switch projects, the compilation appears up to date to th€
Project Manager, even though it has been based on the wronç
APPINCL.H file! “Recompile All Files” addresses this problem.:
Four levels:
1)
FRAMINCL.H
2)
APPINCL.H
3)
FRAMEWRK.H
4)
STRINGS.H, ERRORS.H, FOXPRO.H
I tried to add a website specific include file, WEBINCL.H, between
2) APPINCL.H and 3) FRAMEWRK.H. The theory was that I
wouldn’t need to change any standard Codebook header files,
only APPINCL.H which is meant to be changed. My WEBINCL.H
file could itself #INCLUDE the FRAMEWRK.H file. It didn’t work,
the fifth level of nesting put the constants in STRINGS.H,
ERRORS.H, and FOXPRO.H out of visibility. Needless to say,
the workaround is simple: #INCLUDE the WEBINCL.H header file
in APPINCL.H so it appears with FRAMEWRK.H at level 3 and
does not create a fifth level.
For those interested in a Microsoft-style “Steps to Reproduce the
Problem” proving that four levels is the maximum try, the following
as INCLTEST.PRG:
LOCAL IolnclTestForm
SET CLASSLIB TO
IolnclTestForm
=
CREATEOBJECT(”ClnclTestForm”)
#INCLUDE “incll.h”
DEFINE CLASS cincltesttorm AS form
Caption “Form”
Name
=
“cincltestform”
PROCEDURE mit
?“Message:
“+
SAMPLEMSG
ENDPROC
ENDDEFINE
Create header files INCLI.H through INCL5.H, with each including
the next higher level and INCL5.H containing only the following:
#DEFINE SAMPLEMSG “#DEFINE Was Found.”
When you run it you will get the “Variable SAMPLEMSG
not
Found.” message. Setting the include file from INCLI .H to INCL2.H
fixes the problem; the message “Message: #DEFINE Was Found.”
prints.
A Little Humor.....
There was a man who entered a local paper’s pun contest. He
sent in ten different puns, in the hope that at least one of the
puns would win. Unfortunately, no pun in ten did.
Page 4
|
4 |