As a first step, I tried to get aquainted with your examples, but I
find that the code is prepared for VFP 8. The version I am using right now
is VFP 7. Is there any chance I could get the examples which run on VFP 7?
The framework relies heavily on the data environment
and cursor classes, which were dramatically changed for
version 8.0. Additionally, the use of TRY/CATCH error
handling, which is new to 8.0, causes compile errors
for previous versions of FoxPro.
The concepts in "Build..." apply to all versions of
Visual FoxPro. However, because of the changes to VFP
mentioned above, the sample framework will only run in
One of my objectives with your book is to learn more
about business objects and I have a question. Let's
say I build an invoice object. I can use that object
in a data entry form (InvoiceEntry.scx) or I can
instantiate that object from a program or other form
and call methods, etc. If I have an accounts
receivable form (AR.scx) and I want to use the invoice
object in it, how can I separate the data sessions? It
doesn't seem to be a big deal as long as the AR form
and the Invoice BO use different tables, but if they
share a table (let's say customer) then that table is
aliased in the form data session. It seems I have 2
choices, to open 2 data sessions, 1 for the form and 1
for the BO, or make sure I alias the common tables
differently on the form and the BO. Is this right, or
am I missing something?
I recommend the first scenario; that is, opening two
data sessions, one for the form and one for the
business object. You can see how I’ve done this by
looking at Chapter 11, Framework services, which
illustrates how business objects are created in their
own data session and used independently of a form. Once
the business object is created, you can call to it from
anywhere in your application.
The downside of this approach is that you have to pass
the data from one object to another via a method call.
(However, I don’t consider this much of a downside.)
The second scenario you’ve described is to change the
aliases for common tables. While this may work, I have
often found this more trouble than it is worth.
In the DO CASE of the configureddisplay PROCEDURE,
nDisplayType = 1 calls THIS.PICTURE (instead of THIS.CAPTION)
nDisplayType = 2 calls THIS.CAPTION (instead of THIS.PICTURE)
Assume for a minute you have a save button. At the
class level, the caption may be set to 'Save' and the
picture set to 'SomeSaveImage.bmp'.
Since the command button is capable of displaying both
a picture and a caption, when the button's display type
is 3 (both) the class makes no changes. And, when the
form containing the button is displayed, the user will
see both the word 'Save' and the 'SaveSomeImage.bmp'
When the user chooses to display the picture, the class
sets the caption to an empty string. By removing the
caption, you (the class) leaves only the picture to be
displayed. The user will only see 'SaveSomeImage.bmp'
because the caption is an empty string.
The opposite is true when the user chooses to view
captions only. The caption is left alone and the
picture property is set to and empty string. The user
will see the word 'Save' and no picture.
Either I'm missing something, or there is a missing ENDFUNC
in the main_frame.prg file following line 249 which states:
PROTECTED FUNCTION OnSetAppKeyPad()
There is no ENDFUNC before the next line which reads:
PROTECTED FUNCTION OnLoadData()
Did you know that ENDFUNC and ENDPROC are not needed to end a procedure or function? Well, I was surprised when I first learned that.
Since then, I sometimes stub out a routine like this:
It compiles, and I find it much easier to read.
In the section entitled "Setting up a user" you said I could click
the New button on the toolbar to add new users, but it did not work. New
users never added. Instead of appending blank records to Users.dbf, the
sample application kept appending blank records to Security.dbf.
The MyUser form uses the MySecurityManager class for its data environment. MySecurityManager has an initial selected alias of “Security” and it should have been “Users”. As you correctly state, this results with the appended record in the security table rather than the users table.
I’ve updated the source code to reflect this change.
Figure 29 illustrates which fields are should be marked as updateable. The
CustomerID field is not selected as it should be. Since CustomerID is the
primary key field, the form works properly for edits (because the primary key
does not change during an edit) but does not work properly when adding new