Turning off Modeless Data Entry: Back to the Future in Alpha Five

by Dr. Peter Wayne

Modeless data entry can speed up data entry but it can be dangerous in the hands of an unskilled operator. Alpha Five version 3 offers several ways to turn off modeless data entry. With version 4's OnKey event, you can restore complete compatiblity with Alpha Four and Alpha Five version 1.

Alpha Five version 3 introduced modeless data entry: each table and form is accessible for editing. In previous versions of Alpha products the user had to explicitly switch from data viewing mode to data editing mode. Although I have become accustomed to Alpha Five's modeless data entry, there are times when I turn it off. It's too easy, at least for me, when calling up a new form to hit a stray key and change a pre-existing record. So in many forms I want to turn off modeless data entry until I explicitly want to make new entries.

Fortunately, Alpha Five makes it simple to toggle modeless data entry. I'll show you how it is done in version 3 and then we'll develop a script for version 4 that lets us faithfully emulate the mode-setting keystroke behavior of Alpha Four and A5v1. Even if you've never programmed a script before, I'll take you screen by screen through the process.

Let's begin with a simple table, customer.dbf, with 2 fields, cust_id and cust_balance:

Fig. 1. Structure of Customer table.
Field Type Width and Decimal Points
Cust_ID C 3
Cust_Balance N 6,2

Make a few entries into the default browse of the table:

A few customer entries
Figure 2. A few customer entries.

Now, let's create the default form for this table. We want to modify this form to override modeless data entry. We do this by attaching a small script to the OnInit event of the form. In Form Design mode, choose Actions from the drop-down list under Form:

Choose Actions
Fig. 3. Choose Form, Actions...

And select the OnInit event:

Select OnInit Event
Fig. 4. Select the form's OnInit event.

Choose Code, Convert to Xbasic to bring up the Xbasic code editor:

Convert to Xbasic
Figure 4. Choose Convert to Xbasic to bring up an Xbasic code editor.

In the Xbasic editor, type these lines:

this.restrict_enter=.t.
this.restrict_change=.t.

Script 1. OnInit script for form.

In script 1, this refers to the object that contains the script - in this case, the form. So Script 1 sets the form's restrict_enter and restrict_change properties to .T.. The net result is just as if we had checked off Enter Record and Change Record in the form designer's Properties card:

Form-level restrictions
Figure 5. Form-level restrictions in the form's Properties card.

So why did we write an OnInit script instead of setting these properties in the form designer? Because we're going to change those properties with another script! Properties we set with the form designer are not modifiable, but properties we set with a script can be changed with another script.

Before doing anything else, save this script and then save the form. I called my form "Imitate old Alpha," but you can call it anything you wish. Strictly speaking, you don't have to save the form now, but I've gotten into the habit of saving forms regularly, and I've found that very few crashes occur if you save your work frequently.

Now, in form design mode, drag a button from the Toolbox onto your form. Tell Alpha Five you're going to create a custom button. Make the title of the button "Allow edits," and type the following code into the OnPush event of the button:

parent.restrict_enter=.f.
parent.restrict_change=.f.

Script 2. OnPush script for Allow Edits button.

Notice that in Script 2 we change the properties of the parent obejct, and not the this object. How come? Script 1 was written directly for a form-level event. Script 2 is contained in a button, which in turn is contained in the form. The parent object of the Allow Edits button is the Imitate old Alpha form, and in script 2 we can reference that parent object simply by calling it parent.

Save and run the form. You will see that the form is initially in pure "VIEW" mode - you can't make any changes and you can't create any new records. After you press the Allow Edits button, you can add new records and make changes to any existing records.

However, once we press the Allow Edits button, the form is permanently in a modeless state. Let's write some more code to put the form back into pure "VIEW" mode after each modified record is saved or each new record entered. It's really simple - we just add the lines in Script 1 to the OnSave event of the form:

OnSave event of form

Fig. 6. Put the lines of Script 1 in the OnSave event of the form.

If we're concerned that we might make an inadevertent change as we navigate from record to record, we can add those lines to the OnFetch form event as well:

And the OnFetch event as well

Figure 7. Don't leave out the OnFetch event!

Now, every time you want to create a new record or edit an old record, you have to press the Allow Edits button.

A version 4 refinement

The scripts we outlined above are as far as you can take version 3 in disabling modeless data entry. But in version 4, we can go one step further in imitating the "old Alpha way" by taking advantage of a new event added in version 4, the form's OnKey event. The OnKey event really consists of 3 sub-events:

  1. the "down" event, when the key is pressed down
  2. the "up" event, when the key is released
  3. the "repeat" event, if the key is held down

In addition, there are several reserved variables that only pertain to the OnKey event:

We can code a script for the form's OnKey event to respond to a "C" pressed at the keyboard when the form is in "VIEW" mode. That will emulate the behavior of Alpha Four:

if this.mode_get()="VIEW" then
	if a_user.key.event="down" then
		if upper(a_user.key.value)="C" then
			this.restrict_change=.f.
			a_user.key.handled=.t.
		end if 
	end if 
end if

Script 3. An OnKey script to place the form in change mode.

Although the OnKey event responds both to the "down" and "up" actions when the key is pressed, it's only necessary to look for one of those actions. It's also important to include the line, a_user.key.handled=.t., otherwise the "C" will be passed on to the form.

If you run this script, as I did, you may be a little disappointed when you press the "C" key. The script does place the form in change mode, but you can't see the mode change until you move the cursor off the active field. Then and only then can you make modifications to the record. Is this a flaw in the script? No, it's just a small defect in the way Alpha Five handles the interaction between the form's mode and the table's mode. Now that Alpha Software is aware of it, this problem will no doubt be fixed in one of the maintenance releases for version 4. In the meantime, don't despair: there's an easy workaround. We just have to use the activate() method to move the cursor around a bit, and then the form will be show us that it's in "CHANGE" mode. So our next iteration of Script 3 is:

if this.mode_get()="VIEW" then
	if a_user.key.event="down" then
		if upper(a_user.key.value)="C" then
			this.restrict_change=.f.
			a_user.key.handled=.t.
			cust_balance.activate()
			cust_id.activate()
		end if 
	end if 
end if

Script 4. Moving the cursor with the activate() method.

Script 4 produces an annoying flicker when the OnKey event fires and the cursor does its little dance. We can suppress the flicker with the ui_freeze() function, to produce this next script:

if this.mode_get()="VIEW" then
	if a_user.key.event="down" then
		if upper(a_user.key.value)="C" then
			this.restrict_change=.f.
			a_user.key.handled=.t.
			ui_freeze(.t.) 
			cust_balance.activate()
			cust_id.activate()
			ui_freeze(.f.)
		end if 
	end if 
end if

Script 5. Freezing the output during the cursor manipulation makes for a less distracting screen.

The line, ui_freeze(.t.), stops Alpha Five from updating the screen, while the line, ui_freeze(.f.), restores that ability.

We've covered the "C" key. What about the old "E" key to begin an entry? It's just a natural extension of Script 5, in which we add the new_record() method after testing for an "E":

if this.mode_get()="VIEW" then
	if a_user.key.event="down" then
		select
		case upper(a_user.key.value)="C" 
			this.restrict_change=.f.
			a_user.key.handled=.t.
			ui_freeze(.t.) 
			cust_balance.activate()
			cust_id.activate()
			ui_freeze(.f.)
		case upper(a_user.key.value)="E"
			this.restrict_enter=.f.
	  a_user.key.handled=.t.
			this.new_record()
		end select 
	end if
end if

Script 6. Respond to an "E" key while in "VIEW" mode.

A better DeLorean

In this article we showed how we could restore the familiar data entry modes to Alpha Five version 3 with the use of a few form-level event scripts and a screen button. In version 4, we went one step further, and dispensed with the button entirely, using the "C" key to initiate "CHANGE" mode and the "E" key to launch "ENTER" mode. You may need to use these techniques in applications in which it is very important that inadvertent keypresses do not produce data changes. Take it away, Marty!

10/19/98

Don't forget, we need your feedback to make this site better!

Return to home