Home > Articles

  • Print
  • + Share This
This chapter is from the book

This chapter is from the book

The Form Template

The basic form template for this application is a flat file form. Most, if not all, applications have one or more of these, and some apps have dozens. So it's immediately useful, while still possessing sufficient simplicity to make the code easy to understand. When you catch on to the principles, more complex templates and data access methods should be easy to build.

What's a little tricky is understanding how form templates and the data tier interact. During the Depression, my father said that a humorous way of dismissing the difficult situation at hand was to say "If we had some ham we could have ham and eggs. If we had some eggs...." The form template and the data tier are each written with the other's function in mind. The reusable components go in the data tier, and the calls to use these components go in the template.

For example, Listing 3.5 shows the class code for my FlatFileForm template. I'll comment it as we go.

Listing 3.5 The FlatFileForm Class

MainTable  = .F.   && Name of the main table for the form
KeyField  = .F.   && Name of the Primary Key for the Main Table
KeyValue  = .F.   && Value in the KeyField of the current record
Beforeadd  = .F.   && Record number before adding (used when Add is canceled)
SearchForm = .F.   && Name of a "pick one" form called by the Find button
Adding   = .F.   && True at "Save" time if "Add" button was clicked
Inputfields = "MYTEXT,MYCHECK,MYEDIT,MYCOMBO,MYSPIN,MYDATE"
* Classes to enable/disable
Beforeadd  = 0   && Record pointer value before an add or edit begins
PROCEDURE Buttons   && Turns form buttons on or off as needed
LPARAMETERS OnOff
WITH THISFORM
.cmdAdd.Enabled   = OnOff
.cmdFind.Enabled  = OnOff
.cmdClose.Enabled  = OnOff
.cmdEdit.Enabled  = OnOff AND RECCOUNT() > 0
.cmdDelete.Enabled = OnOff AND RECCOUNT() > 0
.cmdSave.Enabled  = NOT OnOff
.cmdCancel.Enabled = NOT OnOff
.cmdClose.Cancel  = OnOff
.cmdCancel.Cancel  = NOT OnOff
ENDWITH
ENDPROC

PROCEDURE Inputs   && Enables/Disables form controls
LPARAMETERS OnOff
WITH THISFORM
FOR EACH Ctrl IN .Controls
  IF UPPER ( Ctrl.Class ) $ UPPER ( .InputFields )
    Ctrl.Enabled = OnOff
  ENDIF
ENDFOR
.Buttons ( NOT OnOff )
ENDWITH
ENDPROC

PROCEDURE Load    
* Runs when an instance of this form class is instantiated
WITH THISFORM
IF EMPTY ( .MainTable )
  MESSAGEBOX( [No main table specified], 16, [Programmer error], 2000 )
  RETURN .F.
ENDIF
oDataTier.CreateCursor ( .MainTable, .Keyfield )
ENDWITH
ENDPROC

PROCEDURE Init    && Runs after buttons have been instantiated
THISFORM.Buttons ( .T. )
ENDPROC

PROCEDURE Unload   && Closes table or cursor opened by this form
WITH THISFORM
IF USED  ( .MainTable )
  USE IN ( .MainTable )
ENDIF
ENDWITH
ENDPROC

PROCEDURE cmdAdd.Click    && Adds a new record, autopopulating the key field
WITH THISFORM
cNextKey = oDataTier.GetNextKeyValue ( .MainTable )
SELECT ( .MainTable )
.BeforeAdd = RECNO()
CURSORSETPROP( [Buffering], 3 )
APPEND BLANK
IF TYPE ( .KeyField ) <> [C]
  cNextKey = VAL ( cNextKey )
ENDIF
REPLACE ( .Keyfield ) WITH cNextKey
.Refresh
.Inputs ( .T. )
.Adding = .T.
ENDWITH
ENDPROC

PROCEDURE cmdEdit.Click   && Initiates an edit of the current record
WITH THISFORM
SELECT ( .MainTable )
.BeforeAdd = RECNO()
CURSORSETPROP( [Buffering], 3 )
.Inputs ( .T. )
.Adding = .F.
ENDWITH
ENDPROC

PROCEDURE cmdDelete.Click  && Deletes the current record
WITH THISFORM
IF MESSAGEBOX( [Delete this record?], 292, _VFP.Caption ) = 6
  oDataTier.DeleteRecord ( .MainTable, .KeyField )
  DELETE NEXT 1
  GO TOP
  .Refresh
ENDIF
ENDWITH
ENDPROC

PROCEDURE cmdSave.Click   
* Saves data in local cursor and then remotely (if not DBF)
WITH THISFORM
SELECT ( .MainTable )
TABLEUPDATE(.T.)
CURSORSETPROP( [Buffering], 1 )
.Inputs ( .F. )
oDataTier.SaveRecord( .MainTable, .KeyField, .Adding )
ENDWITH
ENDPROC

PROCEDURE cmdCancel.Click  && Cancels an Edit or Add
WITH THISFORM
SELECT ( .MainTable )
TABLEREVERT(.T.)
CURSORSETPROP( [Buffering], 1 )
.Inputs ( .F. )
IF BETWEEN ( .BeforeAdd, 1, RECCOUNT() )
  GO   ( .BeforeAdd )
ENDIF
.Refresh
ENDWITH
ENDPROC

PROCEDURE cmdFind.Click
* If they're using DBF and no search form is defined, use BROWSE
WITH THISFORM
IF EMPTY ( .SearchForm ) AND oDataTier,AccessMethod = [DBF]
  SELECT ( .MainTable )
  .BeforeAdd = RECNO()
  ON KEY LABEL ENTER   KEYBOARD CHR(23)
  ON KEY LABEL RIGHTCLICK KEYBOARD CHR(23)
  BROWSE NOAPPEND NOEDIT NODELETE
  ON KEY LABEL ENTER
  ON KEY LABEL RIGHTCLICK
  IF LASTKEY() = 27
   IF BETWEEN ( .BeforeAdd, 1, RECCOUNT() )
     GO   ( .Beforeadd )
   ENDIF
  ENDIF
 ELSE
  DO FORM ( .SearchForm ) TO RetVal
  IF NOT EMPTY ( RetVal )
   oDataTier.GetOneRecord ( .MainTable, .KeyField, RetVal )
   .Refresh
   .Buttons ( .T. )
  ENDIF
ENDIF
ENDWITH
ENDPROC

PROCEDURE cmdClose.Click  && Da Svidaniya
THISFORM.Release
ENDPROC

How to Use the FlatFileForm Template

To use this template, you do the following eight steps:

  1. Set Field Mappings to use Pinter.VCX and the appropriate controls (MyText, MyChk, and so on) for the data types you use in your tables.

  2. Type the following in the command window:

  3. CREATE FORM "name" AS FlatFileForm FROM Pinter;
  4. Open the form, add the DBF that's the MainTable to the Data Environment, drag and drop the fields to the form, and remove the table from the Data Environment.

  5. Click on Tab Order and pick Rows, and then move the cmdAdd and cmdEdit objects to the top of the Tab Order list.

  6. Set the form's MainTable and KeyField properties to the table name and key field name, respectively.

  7. Remove any fields that you don't want users to enter or edit, like CreateDate or RecordID. (If you prefer, you can browse your SCX, find the controls you want to make noneditable, and change the value in the Class field of the SCX to noedit, which is a disabled TextBox control in pinter.vcx. Because it doesn't appear in the InputFields property list of editable fields, it never gets enabled.)

  8. If you want the KeyField value to appear on the screen, add a label somewhere on the form, and add this code in the form's Refresh method:

  9.      THISFORM.txtKeyField.Caption = ;
          TRANSFORM ( EVALUATE ( THISFORM.MainTable + [.] ;
          + THISFORM.KeyField ))
  10. Add a DO FORM "name" bar to the menu. Recompile and run it, and it ought to work, except for the search form, which is next.

I've followed my instructions and built the little Customer form shown in Figure 3.2 in about 90 seconds.

That's a pretty simple form template, and you might wonder if it really does everything you need. It does if you include the data tier and the search form.

Figure 3.2Figure 3.2 A sample customer form based on the FlatFileForm class.

  • + Share This
  • 🔖 Save To Your Account