Tutorial:
Creating A FoxPro Application
Dr. Thomas E. Hicks
Computer Science Department
Trinity University
For purposes of this tutorial, we shall start with the single user application created in the following tutorial.
Tutorial :
FoxPro Create Application
1] Our RestaruantApp still resides in folder
C:\Temp\RestaurantApp. (See Below!)
2] The Project may be seen below:
Open Database Rest
Use Data\Rest Order Name
Open Database Rest Shared
Use Data\Rest Shared Order Name
2] No longer does it say exclusive at the bottom of the status bar. The active
record on both applications is record 1 of 54. Any function or form that enables
the user to alter a record automatically lock the record as soon as a change is
initiated. Edit and Change are two such functions. In the screen capture
below, The top user is going to and a 2 is added to the end of the restaurant name; you can see
Record Locked in the status
bar as soon as the change is initiated. Once a user locks the record
while making a change, it shall stay locked until the user moves to the next
record.(See Below!)
3] Fortunately, locking the record does not prevent the other users from
searching,running
reports, running labels, examining data, or selection type queries. As you can
see below, the bottom user can attempt to edit the same record and shall be
successful until he/she attempts to make a change. (See
Below!)
4] When the bottom user attempts to add a 2 to the end of the city Odessa, he/she gets a message Attempting To Lock ... Press Esc To Cancel. As soon as the top exits or moves on to another record, the bottom user will get a lock and be able to make his/her change. Really "klugy" at this stage. (See Below!)
5] In the screen capture below, the top user finished editing record 1 and
closed the edit window; the bottom user received a lock on record 1 and is
able to make his/her change to Odessa. (See Below!)
6] Forms only compound these problems!
2] For educational purposes, let us add two temporary buttons to our Rest form. (See Below!)

In other database applications, such as Access, the programmer has to manually create and assign the needed local variables.
2] As you already know, Display Memory, will display all of the local variables -- followed by all of the system variables, etc. In the screen capture below, you can see that local variable NewName was assigned the value Dr.Thomas E. Hicks; Display memory shows this immediately before all of the system variable. (See Below!)

3] The current record is record 1 of 54. The Customer record has 9 fields; the notes field is a memo field. Scatter Memvar Memo creates 9 new local variables whose names are the same as those in the current record and whose values match those of the current record. Scatter Memvar makes a copy of all fields except memo fields. (See Below!)

3] The database field Name takes precedence over the local memory variable Name; therefore, ? Name will display the contents of the field variable Name and ? M.Name will display the contents of the local memory variable Name.
In the screen capture below, both Name and M.Name contain Abstruse Steak House2 because of the scatter. Name = "Joes" will change local memory variable M.Name to "Joes". Replace Name With "Mikes" will change the field Name of the current record to "Mikes". See Below!

2] Program Main must Scatter Memvar Memo prior to launching the form! The first
part of main might be:
Deactivate Windows All Set Default To CurDir( ) Set Near On Set Bell Off Set Deleted On Set Procedure To Programs\Code Open Database Rest Shared Use Data\Rest Shared Order Name Scatter Memvar Memo |
1] If you now run the main program, you will be disappointed that the Next, Previous, Top, and Bottom buttons will definitely not work; try them!
2] From this time forth, it will be necessary to scatter a copy of the memory variables each and every time you move the read/write pointer. Among the procedures that you will have to alter will be Next, Previous, Top, & Bottom. The scatter should occur after the pointer is moved and before the form is refreshed.
3] Functions such as GoTo, Seek, and Skip are among the items that move the
record pointer. I leave it to you to decide exactly which functions need to be
changed. The scatter is included in our new and improved Next procedure below.
Take time now to scatter where-ever you need in the Code.prg.
Procedure Next If EOF() Then GoTo Top EndIf Skip 1 If EOF() Then GoTo Top EndIf Scatter Memvar Memo _screen.activeform.refresh Return EndProc |
4] Run the main program and make sure that your Add, Delete, Next, Previous, Top, Bottom, Delete, and Browse functions still work properly!
Procedure NormalMode *-------------------------------------------------------------------- *-- All Fields Must Be Read Only -- *-------------------------------------------------------------------- _screen.activeform.Name1.ReadOnly = .T. _screen.activeform.Address1.ReadOnly = .T. Return EndProc |
2] Do likewise for the other 8 fields in the Restaurant form. Procedure
NormalMode should have 9 such assignments.
Procedure EditMode *-------------------------------------------------------------------- *-- No Fields Should Be Read Only -- *-------------------------------------------------------------------- _screen.activeform.Name1.ReadOnly = .F. _screen.activeform.Address1.ReadOnly = .F. Return EndProc |
2] Do likewise for the other 8 fields in the Restaurant form. Procedure EditMode should have 9 such assignments.
1] Run the form from your main program. Using the mouse, select/push the Normal Mode button. (See Below!)

2] All of the fields should be read only. Move the cursor into the City field. Try to make a change. If you are able to add something to the end of Kailua, you do not have the field read-only. Try all nine of the data fields. (See Below!)

3] Using the mouse, select/push the Edit Mode button. (See Below!)

4] All of the fields should not be read only. Move the cursor into the City field. Try to make a change. If you are unable to make changes something is wrong. I have added nto to the end of Kailua below. Try all nine of the data fields to make sure that you can change each. (See Below!)

5] At the moment, the form is changing a memory copy of the data record. If you hit the Next and Previous buttons, you will find that the original record has not yet been changed; we will get to that in due time.
1] Once a user enters the Edit Mode, the record will soon be locked; others will not have access to this record. In order to reduce the complexity and encourage the user to quickly exit the Edit Mode, thus freeing the record for others. The Edit Mode shall disable all buttons except the Save and Cancel buttons.
2] The buttons on our form are graphic; we have a disabled picture image and a regular picture image associated with each. You need not associate images with regular buttons.


3] The Edit Mode shall Enable the Save and Cancel Buttons; it shall disable all other buttons. Do not disable the the Normal Mode and Edit Mode buttons; these are here for learning purposes and shall soon be deleted.
Enabled ==>
Disabled ==> ![]()
Procedure EditMode . . . *-------------------------------------------------------------------- *-- Enable Save & Cancel Buttons -- *-------------------------------------------------------------------- _screen.activeform.CancelButton.Enabled = .T. _screen.activeform.SaveButton.Enabled = .T. *-------------------------------------------------------------------- *-- Disable All Other Buttons -- *-------------------------------------------------------------------- _screen.activeform.TopButton1.Enabled = .F. _screen.activeform.TopButton2.Enabled = .F. return EndProc |
4] Don't test yet!
1] Within the Normal Mode, the user shall have access to all buttons except the Save and Cancel.
Procedure NormalMode . . . *-------------------------------------------------------------------- *-- Disable Save & Cancel Buttons -- *-------------------------------------------------------------------- _screen.activeform.CancelButton.Enabled = .F. _screen.activeform.SaveButton.Enabled = .F. *-------------------------------------------------------------------- *-- Enable All Other Buttons -- *-------------------------------------------------------------------- _screen.activeform.TopButton1.Enabled = .T. _screen.activeform.TopButton2.Enabled = .T. return EndProc |
4] Don't test yet!
1] Run the form from your main program. Using the mouse, select/push the Edit Mode button Note that all of the permanent form buttons, except Save & Cancel are disabled. (See Below!)

2] Using the mouse, select/push the Normal Mode button Note that only the permanent form buttons Save & Cancel are disabled. (See Below!)

3] The form should be initiated in the normal mode. Once the form is launched, the main program should evoke the NormalMode procedure. (See Below!)
** Declare Public variables in which to hold the Main form Public __RestForm ** Load form Rest and associate it with __RestForm - For Show & Hide Do Form Forms/Rest Name __RestForm linked Do NormalMode ** Remove the FoxPro window __RestForm.application.visible = .F. * The Line Below Requied For Compiled Applications Read Events |
1] The Add Procedure shall
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
*- Procedure Add -*
*- -*
*- Purpose : Load a blank form and allow the user to Save or -*
*- Cancel. Save will append a new record with the -*
*- appropriate data. -*
*- Called From : Valid Event of Add Button. -*
*- -*
*- Written By: Dr. Thomas E. Hicks App: Visual FoxPro 6 -*
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Procedure Add
__AddMode = .T.
Scatter Memvar Memo Blank
Do EditMode
_screen.activeform.refresh
_screen.activeform.Name1.SetFocus
Return
EndProc
|
2] Remember to add global variable__AddMode to your main program; initialize it to false.
Public __AddMode
__AddMode = .F.
3] The form should look like the following once the Add button is selected/pushed.

3] We realize that a record has not been added to the database yet. If the user cancels this new insertion, there is no need to add a record that we would have to delete.
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* *- Procedure Cancel -* *- -* *- Purpose : Return to the Normal Mode and refresh the form. -* *- Called From : Cancel Button for both Add and Edit -* *- functionality. -* *- -* *- Written By: Dr. Thomas E. Hicks App: Visual FoxPro 6 -* *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Procedure Cancel Scatter Memvar Memo Do NormalMode __AddMode = .F. _screen.activeform.refresh Return EndProc |
2] The Save procedure shall
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* *- Procedure Save -* *- -* *- Purpose : If the mode is Add - Append a new blank record. -* *- Use Gather command to load local memory variables -* *- into the database record. Return to the Normal Mode -* *- and refresh the form. -* *- Called From : Save Button for both Add and Edit Functionality. -* *- -* *- Written By: Dr. Thomas E. Hicks App: Visual FoxPro 6 -* *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Procedure Save If (__AddMode = .T.) Append Blank __AddMode = .F. EndIf Gather Memvar Memo __AddMode = .F. Do NormalMode _screen.activeform.refresh Return EndProc |
3] Check out the Add and make sure that both the cancel and save functionality
work properly!
1] The Edit procedure shall
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* *- Procedure Edit -* *- Purpose : Attempt to lock the record. If the record is locked, -* *- inform the user. If the recod is not locked, lock it -* *- and enter the Edit Mode. -* *- Called From : Edit Button. -* *- -* *- Written By: Dr. Thomas E. Hicks App: Visual FoxPro 6 -* *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Procedure Edit Set Reprocess To 0 Seconds LockStatus = Lock() If (LockStatus = .F.) Then Wait Window "This Record Is Locked By Another User" TimeOut 5 Else Do EditMode _screen.activeform.Name1.SetFocus EditMode = .T. EndIf Return EndProc |
2] The Cancel procedure will need to be altered to terminate the Edit
functionality. (See Below!)
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* *- Procedure Cancel -* *- -* *- Purpose : Return to the Normal Mode and refresh the form. -* *- Called From : Cancel Button for both Add and Edit -* *- functionality. -* *- -* *- Written By: Dr. Thomas E. Hicks App: Visual FoxPro 6 -* *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Procedure Cancel Scatter Memvar Memo Do NormalMode __AddMode = .F. __EditMode = .F. _screen.activeform.refresh Return EndProc |
3] The Save procedure will also need to be altered to terminate the Edit
functionality. (See Below!)
*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* *- Procedure Save -* *- -* *- Purpose : If the mode is Add - Append a new blank record. -* *- Use Gather command to load local memory variables -* *- into the database record. Return to the Normal Mode -* *- and refresh the form. -* *- Called From : Save Button for both Add and Edit Functionality. -* *- -* *- Written By: Dr. Thomas E. Hicks App: Visual FoxPro 6 -* *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* Procedure Save If (__AddMode = .T.) Append Blank __AddMode = .F. EndIf Gather Memvar Memo Scatter Memvar Memo Do NormalMode __EditMode = .F. _screen.activeform.refresh Return EndProc |