IT SOLUTIONS
Your full service technology partner! 
-Collapse +Expand
Paradox
Search Paradox Group:

Advanced
-Collapse +Expand Paradox To/From
To/FromCODEGuides
-Collapse +Expand Paradox Store
PRESTWOODSTORE

Prestwood eMagazine

October Edition
Subscribe now! It's Free!
Enter your email:

   ► KBDesktop Data...Paradox & Ob...P9 Book: Pow...   Print This     
  From the April 2012 Issue of Prestwood eMag
 
Paradox P9 Book: Power Programming:
Power: Chapter 19, Imitate Users with Action, PostAction, and MenuAction
 
Posted 21 years ago on 3/26/2003 and updated 3/5/2006
Take Away: Chapter 19, "Imitate Users with Action, PostAction, and MenuAction" from Paradox 9 Power Programming by Mike Prestwood.

KB100214

Whenever you interact with Paradox, you generate either an Action or MenuAction constant. For example, when you select a menu item, a constant is sent to the built-in menuAction event. If the constant maps to an Action constant, an equivalent Action constant then is sent to the built-in action event. For example, when you select File | Print, the constant MenuFilePrint is sent to the form’s menuAction event. Since MenuFilePrint maps to the action constant DataPrint, DataPrint is sent to action. In the events action and menuAction, you can trap for nearly every user interaction. In addition, using the action() and menuAction() methods you can invoke or imitate nearly any user interaction by sending Action and MenuAction constants to the built-in action and menuAction events.

Action() and PostAction()

Both action() and postAction() performs a specified action. The difference is that action() executes the action right away and postAction() posts an action to an action queue for delayed execution. With postAction(), the action is posted to an action queue at the time of the method call; Paradox waits until a yield occurs—for example, by the current method completing execution or by a call to sleep(). This is an important distinction to keep in mind while executing actions from within your code.

Using the action() and postAction()

These methods open up a whole bunch of commands. As an ObjectPAL programmer, you’re interested in five action constant classes: ActionDataCommands, ActionEditCommands, ActionFieldCommands, ActionMoveCommands, and ActionSelectCommands. Use these commands with the action() method. The syntax for action constants is as follows:

ObjectName.action(ActionConstant)

ObjectName is the name of the object on which you want the action to occur, such as theBox or Last_Name. The actionConstant can be any constant category whose name starts with action. If you want, you can precede this expression with an object path, as in the following:

1: f.pge3.tf.action(DataNextRecord)

In the above, f is a handle to another form, and pge3 and tf are the names of two objects contained in the form (the third page and its table frame). The constant DataNextRecord moves the cursor forward one record (if possible).

Using Action Constants

The constants in the ActionDataCommands category deal with data in a table as a whole, as shown here:

Illustration 1

They are used for navigating the pointer in a table, locking a record, posting a record, toggling Edit mode, and positioning the record pointer. Following are three examples:

action(DataPrint) ;Prints a form or table view.
action(DataTableView) ;Open the master table in a window.
action(DataSaveCrosstab) ;Writes the crosstab data
;to :PRIV:CROSSTAB.DB.

ActionEditCommands

In general, the constants in the ActionEditCommands category are used for altering data within a field, as shown here:

Illustration 2

With these constants, you can copy text to the Clipboard, enter persistent field view, access the help system, and search your text. Following are three examples:

1: action(EditDropDownList) ;Drops down pick list.
2: action(EditEnterMemoView) ;Enters memo view.
3: action(EditPasteFromFile) ;Pastes from file into
;current field.

ActionFieldCommands

The constants in the ActionFieldCommands category are used for moving between field objects, as shown here:

Illustration 3

With these constants, you can invoke and control tab order. You can move the focus forward or backward in the tab order. You can ignore the tab order and move up, down, left, or right. You can even move from one table frame to another. Following are three examples:

1: action(FieldRotate) ;Rotates columns in a table frame
2: action(FieldNextPage) ;Moves to the next page in a form
3: action(FieldForward) ;Moves one field forward

ActionMoveCommands

The constants in the ActionMoveCommands category are used for positioning within a field object, as shown here:

Illustration 4

With these constants, you can move to the beginning or end of a field, move left one word, or scroll a field up or down. In general, these commands behave differently in a Memo field than they do in a set of fields. Following are three examples:

action(MoveEnd) ;Moves to the end of the document or
;to last field.
action(MoveLeftWord) ;Moves cursor to word on the left.
action(MoveScrollPageDown) ;Scrolls the page image down.

ActionSelectCommands

The ActionSelectCommands constants are similar to the ActionMoveCommands constants, but you use them to select data within a field object, as shown here:

Illustration 5

With these constants, you can select from the current position to the beginning of the document. Following are three examples:

1: action(SelectEnd) ;Select to the end.
2: action(SelectLeft) ;Selects one character to the left.
3: action(SelectSelectAll) ;Selects the entire document.

Browse through the online constants section by selecting View | ObjectPAL Quick Lookup and selecting the Constants tab. Select the categories whose names start with action. These constants are your gateway to more powerful data manipulation and, therefore, to more powerful applications.

Tip: If you find a constant that is not self-explanatory, search in the help for types of constants for a complete list of the constants along with a description for each.

Trapping Action Constants

In addition to executing action constants, you can trap for them. The basic idea is to use the action event and inspect the eventInfo variable. For example, to trap for when the form enters Edit mode, type lines 3–6 in the page’s action event.

1: ;Commands :: Pge1 :: action
2: method action(var eventInfo ActionEvent)
3: if eventInfo.id() = DataBeginEdit then
4: DoDefault ;Finish moving into edit mode.
5: beep()
6: msgInfo("Careful", "You are now in edit mode.")
7: endIf
8: endMethod

Using MenuAction Constants

Another method in ObjectPAL that opens up a whole world of power is menuAction(). The menuAction() method enables you to execute any of the MenuCommand constants, shown next. Any time you want to execute or trap a menu-equivalent task, consider using the menuAction() method or menuAction event.

Illustration 6

To display the Form Open dialog box, for example, add line 3 to the pushButton event of a button.

1: ;Commands :: btnMenuAction :: pushButton
2: method pushButton(var eventInfo Event)
3: menuAction(MenuFormOpen)
4: endMethod

Trapping MenuAction Constants

Just as you can trap for action constants, you can trap for MenuCommand constants. For example, to trap for the user pressing the Form Maximize button, add lines 3–5 to the menuAction event of a page.

1: ;Commands :: Pge1 :: menuAction
2: method menuAction(var eventInfo MenuEvent)
3: if eventInfo.id() = MenuControlMaximize then
4: disableDefault
5: endIf
6: endMethod

Action Constants and Bubbling

The following table lists the action classes. As you can see, most action events do not bubble. In fact, only ActionDataCommands bubble. You can use eventInfo.actionClass() to return the class of an action event.

ActionEvent

Bubble?

Description of Action

ActionDataCommands

Yes

Deal with the whole form

ActionEditCommands

No

Deal with editing data

ActionFieldCommands

No

Move from field to field

ActionMoveCommands

No

Move the cursor within a field

ActionSelectCommands

No

Select data within a field

Identifying Action and Error Constants

Sometimes it is necessary to identify a constant. Either you need to trap for it or you want to execute it. Either way, finding the action constant that maps to a specific task can be daunting. Using constantValueToName() enables you to extract the name of a constant from a number. The syntax for constantValueToName() is as follows:

constantValueToName ( const groupName String, const value AnyType,
var constName String ) Logical

This method is very helpful in developing an application when you want to know which actions are being triggered. The one weakness of this method is that you have to specify the group type. For example, you have to specify ActionDataCommand, ActionMoveCommand, Error, and so on.

The following code snippet from http://prestwood.com/forums/paradox/books/official/files/ID_Actions.fsl demonstrates how to extract the name of an action or error constant from eventInfo, as shown next. For demonstration purposes, this code is called from the action event of the form; this code displays every action generated and every error generated. It uses actionClass() to extract the class of action constant. It also demonstrates using a list object to scroll values. It uses a private custom procedure, which helps make it structured. (For more on structured programming, refer to Appendix A.)

Illustration 7

You can follow the actions I took in the illustration above. I first tried to insert a record and couldn’t because I wasn’t in Edit mode. This generated a peNotInEditMode error. I then toggled into Edit mode, moved to the Customer No field, entered a number, moved to the Name field and pasted a name in. Read through the code and see whether you can follow the logic; start from the method prototype line.

1: ;ID_Actions :: Form :: cmIdentifyConstant
2: proc cpDisplayConstant(sConstantType String, sConstant String)
3: ;Display constant class & constant in list field.
4: ;This procedure is used by cmIdentifyConstant.
5: beep()
6: ;lstConstant is a list object of a list field placed on the form.
7: lstConstant'list.selection = lstConstant'list.count + 1
8: lstConstant'list.value = sConstantType + " :: " + sConstant
9: endProc
10:
11: method cmIdentifyConstant(var eventInfo ActionEvent)
12: ;Identify constant.
13: var
14: sConstant String
15: siConstantType SmallInt
16: sConstantType String
17: siID SmallInt
18: endVar
19:
20: ;Check for an error.
21: if eventInfo.errorCode() <> peOk then
22: constantValueToName("Errors", eventInfo.errorCode(),
sConstant)
23: cpDisplayConstant("ErrorCode", sConstant)
24: return
25: endIf
26:
27: ;Identify action constant.
28: siConstantType = eventInfo.actionClass()
29: siID = eventInfo.id()
30: switch
31: case siConstantType = DataAction
32: : sConstantType = "DataAction"
33: constantValueToName("ActionDataCommands", siID, sConstant)
34: case siConstantType = EditAction
35: : sConstantType = "EditAction"
36: constantValueToName("ActionEditCommands", siID, sConstant)
37: case siConstantType = FieldAction
38: : sConstantType = "FieldAction"
39: constantValueToName("ActionFieldCommands", siID, sConstant)
40: case siConstantType = MoveAction
41: : sConstantType = "MoveAction"
42: constantValueToName("ActionMoveCommands", siID, sConstant)
43: case siConstantType = SelectAction
44: : sConstantType = "SelectAction"
45: constantValueToName("ActionSelectCommands", siID, sConstant)
46: otherwise
47: : ;This should never get called.
48: sConstantType = "unknown"
49: sConstant = "unknown"
50: endSwitch
51:
52: cpDisplayConstant(sConstantType, sConstant)
53: endMethod

The following code calls the custom method. Notice that doDefault is called before eventInfo is passed to the custom method.

1: ;ID_actions.fsl :: Form :: action
2: method action(var eventInfo ActionEvent)
3:
4: if eventInfo.isPreFilter() then
5: ;// This code executes for each object on the form
6: ;//
7: DoDefault
8: cmIdentifyConstant(eventInfo)
9: else
10: ;// This code executes only for the form
11: ;//
12:
13: endIf
14:
15: endMethod

You might want to put a variation of the preceding custom method into your standard library—perhaps alter it to return the action constant. After you do this, you can use it from time to time when you code to determine an action constant name that is giving you problems.

Tip: To send a list of all the constants to a table, create and run the following one-line script:
enumRTLConstants("CONST.DB")
This script creates a table that has all constants, including all the error constants. Use this table to create reports in any order you like.

Manipulating a Memo Field

To manipulate the font attributes and text of a Memo field use the action() method. The basic technique is to pass the action() method an action constant:

object.action( ActionConstant )

For example, the following selects all the text in a Memo field:

1: ;Form :: Var
2: method pushButton(var eventInfo Event)
3: fldMemo.action(SelectSelectAll)
4: endMethod

Time and Date Stamping a Memo Field

To time stamp and add a note to the end of a Memo field, use lines 3–7.

1: ;Button :: pushButton
2: method pushButton(var eventInfo Event)
3: edit()
4: Notes.moveTo()
5: Notes.value = Notes.value + chr(13) + String(DateTime()) + chr(13)
6: Notes.action(EditEnterMemoView)
7: Notes.action(MoveEnd)
8: endMethod

To time stamp and add a note to the beginning of the Memo field, use lines 3–8.

1: ;Button :: pushButton
2: method pushButton(var eventInfo Event)
3: edit()
4: Notes.moveTo()
5: Notes.value = String(DateTime()) + chr(13) + chr(13) + Notes.value
6: Notes.action(EditEnterMemoView)
7: Notes.action(MoveBegin)
8: Notes.action(MoveDown)
9: endMethod

Identifying menuAction Constants

Steps for using the MenuID form:

  1. Select a menu option to generate a menu constant.
  2. Put the constant or number in the MenuAction field (the constant is always preferred). You can just click on the constant displayed below the Execute Menu Constant button.
  3. Press the button to make sure it works.

Illustration 8

The interesting bit of code is in the page’s menuAction event and in the pushButton event of the button. The following is the code in menuAction that traps the menu constants:

1: ;MENUID :: page :: menuAction
2: method menuAction(var eventInfo MenuEvent)
3: var
4: s String
5: endVar
6:
7: if eventInfo.isPreFilter() then
8: ;// This code executes for each object on the form:
9:
10: else
11: ;// This code executes only for the form:
12: switch
13: case eventInfo.id() = MenuInit
14: : ;Occurs when the menu option is selected.
15: ;Do nothing.
16: case eventInfo.id() = MenuBuild
17: : ;Occurs when the menu is first built.
18: ;Do nothing.
19: case eventInfo.id() = MenuControlKeyMenu
20: : ;Menu selected via a key press.
21: ;Do nothing.
22: otherwise
23: : if fldDisplay.value = "Yes" then
24: constantValueToName("MenuCommands", eventInfo.id(), s)
25: msgInfo(eventInfo.id(), s)
26: endIf
27: endSwitch
28: constantValueToName("MenuCommands", eventInfo.id(), s)
29: fldStatus.value = s
30: endMethod

The following is the code in the pushButton event of the button that uses a try block to first try to execute a MenuCommand number and then uses a constant.

1: ;MENUID :: btnExecute :: pushButton
2: method pushButton(var eventInfo Event)
3: ;Try to execute number.
4: try
5: menuAction(fldMenuAction)
6: onFail
7: ;Convert String to number.
8: try
9: menuAction(ConstantNameToValue(fldMenuAction.value))
10: onFail
11: msgStop("Warning", "Invalid menu constant.")
12: endTry
13: endTry
14: endMethod

Summary

In this chapter, you learned you can imitate nearly any user interaction by sending action and menuAction constants to the action and menuAction events using the action() and menuAction() methods. In addition, you learned how to trap for most user interactions in the action and menuAction events. Finally, you learned how to use the ID_Action and MenuID forms to identify action and menuAction constants.


Comments

0 Comments.
Share a thought or comment...
 
Write a Comment...
...
Sign in...

If you are a member, Sign In. Or, you can Create a Free account now.


Anonymous Post (text-only, no HTML):

Enter your name and security key.

Your Name:
Security key = P157A1
Enter key:
KB Post Contributed By Mike Prestwood:

Mike Prestwood is a drummer, an author, and creator of the PrestwoodBoards online community. He is the President & CEO of Prestwood IT Solutions. Prestwood IT provides Coding, Website, and Computer Tech services. Mike has authored 6 computer books and over 1,200 articles. As a drummer, he maintains play-drums.com and has authored 3 drum books. If you have a project you wish to discuss with Mike, you can send him a private message through his PrestwoodBoards home page or call him 9AM to 4PM PST at 916-726-5675 x205.

Visit Profile

 KB Article #100214 Counter
13884
Since 4/2/2008
Go ahead!   Use Us! Call: 916-726-5675  Or visit our new sales site: 
www.prestwood.com


©1995-2024 Prestwood IT Solutions.   [Security & Privacy]