VFP 6 changes our approach to projects. There's no longer a need to hack
the PJX file, because VFP 6 provides a new interface to projects: Whenever
a project is opened, a Project object is now instantiated. Interestingly,
Project objects are Automation -- not native VFP -- objects. This has several
consequences:
There are two ways you can work with a Project object: through the Application
(or _VFP) Projects collection or with Application.ActiveProject. Similar
to VFP's Forms collection and ActiveForm property, there's an object reference
to every open project in the Projects collection and a reference to the
active project in the ActiveProject property. Like ActiveForm, ActiveProject
is undefined (the TYPE function returns "U") when there's no open
project.
As if Project objects weren't enough, VFP 6 also gives us ProjectHook objects.
A ProjectHook object may be automatically instantiated when a project is
opened (you have complete control over whether ProjectHooks are used or
not), and its events are fired whenever something is done to the project:
adding or removing files, modifying or running files, or building the project.
ProjectHook is a new VFP base class, so we can create our own ProjectHook
classes and put any code into them we want. Thus, we have a hook into the
operation of the Project Manager, and we can even completely manipulate
projects without using the Project Manager at all.
Because you'll need some background into Project objects and ProjectHooks
before you can build some tools using them, this article will have more
background than is usual for my articles. Please bear with me; I'll get
to the good stuff soon.
Project object model
The object model for the Projects collection
and Project objects is shown in Figure
1. As you can see, a Project object contains a
reference to a ProjectHook object and has both Files and Servers collections.
We'll look at these objects and collections, as well as their properties,
events, and methods.
Projects collection
The Projects collection only has one
property, Count (the number of Project objects in the collection), and one
method, Item (which returns a reference to the specified project). Here
are some examples:
|
|
|
Property | Access | Type | Description |
AutoIncrement | R/W | L | .T. to increment the VersionNumber property when an EXE or DLL is built. |
BuildDateTime | R/O | T | The date and time of the last build. |
Debug | R/W | L | .T. to include debugging information for each compiled file. |
Encrypted | R/W | L | .T. to encrypt files as they're compiled. |
Files | R/O | Coll | A collection of File objects. |
HomeDir | R/W | C | The home directory of the project. |
Icon | R/W | C | The icon used when building an EXE. |
MainClass | R/O | C | The name of the ActiveDoc class used as the main program (only used when MainFile contains the name of the VCX where this class is defined). |
MainFile | R/O | C | The main program in the project, set using the SetMain method. |
Name | R/O | C | The name of the project, including the fully qualified path. |
ProjectHook | R/W | O | A reference to the ProjectHook object associated with the project. |
ProjectHookClass | R/W | C | The name of the class from which the ProjectHook object is instantiated. |
ProjectHookLibrary | R/W | C | The class library in which the ProjectHook class is defined. |
SCCProvider | R/O | C | The name of the source code control provider if the project is under source code control. |
ServerHelpFile | R/W | C | The name of the Help file for the typelib used for server classes. |
ServerProject | R/W | C | The first part of the ProgID for the Automation server created by the project; the default is the same as the Name property. |
Servers | R/O | Coll | A collection of Server objects. |
TypeLibCLSID | R/O | C | The typelib Registry CLSID. |
TypeLibDesc | R/W | C | The typelib description. The default is the name of the project + "Type Library". |
TypeLibName | R/O | C | The fully qualified path to the typelib for the project. |
VersionComments | R/W | C | Version comments. |
VersionCompany | R/W | C | Version company name. |
VersionCopyright | R/W | C | Version copyright. |
VersionDescription | R/W | C | Version description. |
VersionNumber | R/W | C | Version number in Major.Minor.Revision format. |
VersionProduct | R/W | C | Version product name. |
VersionTrademarks | R/W | C | Version trademarks. |
Visible | R/W | L | .T. (the default) to display the Project Manager. |
Table 1:
Project object properties.
Project objects have the following methods (see the VFP documentation for
syntax):
|
|
Files collection
The Files collection is a collection
of File objects, one for each file in a project. It has one property, Count
(the number of files in the collection), and two methods, Item (which returns
a reference to the specified file) and Add (which adds a file to the project
and returns an object reference to it). Here are some examples:
|
Property | Access | Type | Description |
CodePage | R/O | N | The code page for the file. |
Description | R/W | C | The description shown in the Project Manager. |
Exclude | R/W | L | .T. if the file is excluded from the project. |
FileClass | R/O | C | The class a form is based on. |
FileClassLibrary | R/O | C | The library the form's class is defined in. |
LastModified | R/O | T | The date and time the file was last modified. |
Name | R/O | C | The name of the file, including the fully qualified path. |
ReadOnly | R/O | L | .T. if the file is read-only. |
SCCStatus | R/O | N | The source code control status of the file. "0" means the file isn't source controlled; see the VFP documentation for other values (such as checked out or not). |
Type | R/O | C | The file type: V for VCX, P for program, R for report, B for label, K for form, Q for query, L for API library, D for table, d for database, Z for APP, M for menu, T for text, and x for other. |
Table 2: File object properties.
File objects have the following methods (see the VFP documentation for syntax):
Servers collection
The Servers collection is a collection
of Server objects, one for each Automation server in a project. It has one
property, Count (the number of files in the collection), and one method,
Item (which returns a reference to the specified server).
Server object
The properties of Server objects are
listed in Table 3;
properties common to all VFP base classes are omitted.
Property | Access | Type | Description |
CLSID | R/O | C | The Registry CLSID for the server. |
Description | R/W | C | The server's description in the Registry. |
HelpContextID | R/W | N | The help context ID for the typelib. |
Instancing | R/W | N | Specifies how the server is instantiated: 1 (the default) for single use, 2 for not creatable outside of VFP, or 3 for multi-instance. |
ProgID | R/O | C | The Registry ProgID for the server. |
ServerClass | R/O | C | The class name of the server. |
ServerClassLibrary | R/O | C | The library the server class is defined in. |
Table 3:
Server object properties.
ProjectHooks
As I mentioned earlier, VFP has a new ProjectHook
base class. A ProjectHook object may be automatically instantiated when
a project is opened (you have complete control over whether ProjectHooks
are used or not), and its events are fired whenever something is done to
the project: adding or removing files, modifying or running files, or building
the project. Like Project objects, ProjectHooks are actually ActiveX objects,
not native VFP objects.
You can set a ProjectHook for individual projects or globally. To specify
which ProjectHook class to use for an individual project, choose the Project
page of the Project Info dialog box, and choose the desired class for the
Project Class. You can also set the ProjectHookClass and ProjectHookLibrary
properties of the Project object, although this won't instantiate the ProjectHook
class until the project is closed and reopened. To set a ProjectHook for
all projects that don't have individually specified ProjectHooks, use the
Projects page of the Tools Options dialog box. You can also instantiate
a ProjectHook object and store a reference to it in a Project object's ProjectHook
property, but this provides a non-persistent hook to the project.
Once a ProjectHook class has been specified for a project, the ProjectHook
object is automatically instantiated whenever the project is opened, and
it's destroyed when the project is closed. If you want to open a project
but not instantiate the ProjectHook, use the new NOPROJECTHOOK clause of
the MODIFY PROJECT command. You can also use NOPROJECTHOOK with CREATE PROJECT
to create a project without the global ProjectHook. These two commands have
another new clause, NOSHOW, that instantiates the Project and ProjectHook
objects but doesn't display the Project Manager, so you can manipulate a
project without any user interface at all.
ProjectHook events
ProjectHook objects don't have any properties
beyond those of other VFP base classes, but they have several specific events
that automatically fire when something is done to the project (see the VFP
documentation for parameters these events receive):
Extending functionality
Because a ProjectHook object is automatically
instantiated when a project is opened from a user-defined class, and its
events are automatically called when something is done with the project,
you have the ability to define what happens when the user works with a project.
I'm sure you can think of all kinds of things you could do with this capability;
I'll discuss some of the ideas I've come up with.
Before I discuss what types of tools you can build, however, keep one thing
in mind: Avoid the temptation to build a ProjectHook with everything in
it, including the kitchen sink. There are a number of good reasons for making
your ProjectHook classes granular:
There are several ways you can build modular ProjectHook classes and use
dynamic composition to put them together:
Conclusion
Thanks to the new Project objects and ProjectHooks
in VFP 6, we can now add to or change the behavior of the Project Manager.
This allows us to create tools that give us more capabilities or more productivity
than we get with the Project Manager. I expect we'll be seeing a lot of
such tools in the months ahead.
Doug Hennig is a partner with
Stonefield Systems Group Inc. in Regina, Saskatchewan, Canada. He is the
author of Stonefield's add-on tools for FoxPro developers, including Stonefield
Database Toolkit and Stonefield Query. He is also the author of The Visual FoxPro Data Dictionary in Pinnacle
Publishing's The Pros Talk Visual FoxPro series. Doug has spoken
at the 1997 and 1998 Microsoft FoxPro Developers Conferences (DevCon), as
well as user groups and regional conferences all over North America. He
is a Microsoft Most Valuable Professional (MVP). 75156.2326@compuserve.com,
dhennig@stonefield.com.