[ 1 ] [ 2 ] [
3 ] [ 4 ] [
5 ] [ 6 ] [
7] [ 8 ] [
Table with Form Mediator PEMs
Hold the name of a context toolbar
class and classlibrary you wish to attach to this mediator's host document.
This item and the context menu file, below, can be used alongside the
"go" menu and toolbar provided by the framework if you like.
Unlike the "go" menu and toolbar, these are intended to be completely
outside the framework, application- or form-specific items. The
framework will share them among forms and dispose of them when no form
Hold the name, menu popup name,
and menu pad name of a context menu you wish to attach to this mediator's
host document. See above for intended use.
Stores information about whether
the framework invoked the host document as "new" or "open".
Specify whether or not the host
document has been assigned a navigation toolbar and/or menu by the application
and its metatable entry. This happens automatically (you don't need
to set these properties).
The two logical properties specify
whether the mediator should load session settings using the application's
defaults, and whether the mediator should load data-session-specific user
settings using the application's information about user preferences.
The first of these defaults to .F., and is a convenience you may not need
or want to use – it’s likely to happen too late in the startup session
to be reliable for your table-opening needs. If you rely on this
ability, also, you are implicitly saying that the form will not be used
outside the framework (since many of these settings, such as SET MULTILOCKS,
are critical to table behavior).
The second defaults to .T., and will be appropriate in most instances.
More about this feature below, in the section on Options.
DoSessionSets(), which evaluates these two logical properties and applies
them as necessary, will happen at startup but may be called later if the
user changes options while the form is running.
GetAppRef ( )
The cAppRef property holds
the name of the reference variable for the running app so the mediator
can evaluate it to an object reference when necessary. The mediator
does not store any object references, for safety. Instead, it or
its clients use GetAppRef to RETURN an object reference to the app whenever
LoadApp() is called by the application
object when this form or formset is instantiated, if the mediator object
is available. This gives the mediator a chance to store the reference
string it needs to get an app reference later, and to apply app attributes
to a form, including session settings, as directed by its lSessionSettings
and lUserSessionSettings properties. If context menu file or toolbar items
are filled out, the mediator tells the App to manage this menu and/or
toolbar during LoadApp() as well. If lAddAppIcon is .T., which is the
default, LoadApp will apply the application's standard Icon to the form's
Icon property if the form's Icon property has been left empty.
The first method here wraps the
app DoTableOutput() method. The second wraps it passing a scope of one
record. Either of these methods can be used with the cOutput… properties
below. These methods are intended to allow you to provide quick
output from a form or perhaps a form button.
This set of properties and methods
is intended to "focus" the form's use of the DoTableOutput()
method provided by the application object. DoTableOutput provides
quick, table-oriented output of various sorts and to various devices,
even when no appropriate report is available.
Left to itself, DoTableOutput(), which the user may call at any time from
a the standard toolbar's "print" button or the menu, will simply
focus on the current alias in the current data session. If DoTableOutput()
finds a mediator, however, it will look for alternative information using
these properties and methods.
If you have filled out cOutputAlias, it knows you mean this alias to be
SELECTed for the purposes of table output. If cOutputCaption is
filled out, it will show up when the application object instantiates the
output dialog, to serve as the dialog's caption.
The two methods here are abstract. They're designed when you need
to do more than simply SELECT a table for output. DoTableOutput()
calls these methods when the mediator exists, giving you a chance to put
together a cursor, filter data, or otherwise prepare an appropriately
"output-focused" table with information before output, and destroy
The DataChanged() method wraps the
application's QueryDataChanged() method for use by this form and its members.
QueryUnload( ) does the same for the application's QueryDataSessionUnload(
) method. You can, and probably should, call this method in the
form's QueryUnload() to handle any data changes, updates, or reverts before
the form is closed in the same manner the application will handle it when
the user tries to exit the application.
IChangeMode is sent on to the app's
cusDataSession object to determine what constitutes a "data change"
during this process. See the _datasession object in FFC's _APP.VCX for
SetDocumentToNew stores the app's
lAddingNewDocument flag at the time the app attributes are loaded, so
the form can evaluate what record to work on.
PickRecordToWorkOn is an abstract
method, designed to make use of this information and to allow you to decide
what you want to do with the form and the new/open information the framework
has given it.
It isn't called directly, because it's up to you and your data handling
to decide when to call it (when you've loaded your data) and what should
happen then. In "open" mode, do you want to add a browse
for the user to pick a record? Do you want to determine this record using
an application cCurrentID property you invent? In "new" mode,
should you APPEND a BLANK, and to which table in this data session?
How does your form take advantage of these features? Any form with a mediator,
even one added at runtime, will get certain basic services. If it is built by
the Wizard, the Wizard form baseclasses will take advantage of the data-handling
PEMs of the form mediator. If you add a mediator to a form manually, and especially
if you subclass the mediator and use your own subclass, obviously you can write
any code and handle the relationship anyway you want.
For a good example of the way a form can use a mediator to access and apply
framework features, take a look at the _ErrorLogViewer class in _FRAMEWK.VCX.
In this dialog, the mediator object augments its DoSessionSets() method to apply
the application object's cTextDisplayFont property, which allows the user or
the application to store a preferred non-proportional font, to a similar property
of the dialog class. An assign method on the dialog's cTextDisplayFont property
then applies this property value to appropriate dialog elements. Since DoSessionSets(
) runs when the dialog first initializes, and then again whenever the user chooses
to apply a new set of preferences through the options dialog, you can watch
these elements change in the error log viewer. This is extremely simple code
leading to a very satisfying result.
This simple code is written directly into the _ErrorLogViewer class and is
directly tailored to this class. However, if you would like to enhance the relationship
between your forms and their mediators, whether base class mediators or your
own subclasses, you will probably wish to automate the relationship in some
Obviously you can build the behavior and the member into your form classes,
and specify these classes for your teams' use. This is the standard way to re-use
and inherit good behavior. But this requirement does not cover all cases and
all forms. It also hides the functionality so that a beginner can't learn about
it, which may be a consideration in some circumstances.
Remember: this framework should take care of any forms built by anybody, not
just ones built to a set of specifications. If, as a senior developer, you know
how you would like this relationship to work, you want access to this relationship
for the first form, built from scratch in the Form Designer, that your apprentice
developer contributes to your application. You provide this access using a Project
The Project Hook functions as a builder for the Project Manager. Like any builder,
you can make its actions automatic and discreet or you can allow an interface
in which the user makes choices.
For this example project hook class, subclassed from the APPHOOK.VCX project
hook class used by the shipping Application Wizard and Builder-generated framework
applications, I've made the action of framework-enabling forms required and
automatic (without an interface). However I've provided a log in which a developer
can see what actions were taken. This seems to be a good compromise; the apprentice
developer doesn't have to understand what's going on to make things work, but
s/he is not left out or manipulated without recourse.
You'll find this project hook object in PHOOK folder of your source code, in
the NEWHOOK.VCX. You attach it to a project using the Project Info dialog.
A subclass of the shipping project hook object produces an "action
log" and some VFP 6 framework-specific additions.
[ 1 ] [ 2 ] [
3 ] [ 4 ] [
5 ] [ 6 ] [
7] [ 8 ] [