PowerBuilder - Events and Precedence
The order in which events happen within a PowerBuilder Classic application is in most cases, a very predictable model. The PB developer should be aware of this aspect when developing GUI based applications. For instance, when focus is shifted from one object to another object, the first object will experience the Modified and LoseFocus events before the second object experiences a get focus event.
To understand this further, consider the following scenarios and the resulting events.
An Application starts and window "A" is opened
APPLICATION OPEN
WINDOW "A" OPEN
WINDOW "A" ACTIVATE
CHILD OBJECT GET FOCUS (First object in tab order)
Window "B" is opened (Window "A" stays open)
WINDOW "A" CURRENT OBJECT LOSE FOCUS
WINDOW "A" DEACTIVATE
WINDOW "B" OPEN
WINDOW "B" ACTIVATE
WINDOW "B" CHILD OBJECT GET FOCUS (First object in tab order)
Window "B" closed, return to Window "A".
WINDOW "B" CLOSEQUERY
WINDOW "B" CURRENT OBJECT LOSE FOCUS
WINDOW "B" CLOSE
WINDOW "B" DEACTIVATE
WINDOW "A" ACTIVATE
OBJECT GET FOCUS (Last object that had focus)
"Click" on new object within Same Window
OBJECT 1 MODIFIED (if changed)
OBJECT 1 LOSE FOCUS
OBJECT 2 GET FOCUS
OBJECT 2 CLICKED
"Tab" to new object within Same Window
OBJECT 1 MODIFIED (if changed)
OBJECT 1 LOSE FOCUS
OBJECT 2 GET FOCUS (next object in tab order)
Interestingly enough, events can and will occur even when no actions are performed by the user. If you are
using a screen saver, such as the one in Windows, the following will happen.
Flip to screen saver (After period of inactivity)
WINDOW DEACTIVATE
OBJECT LOSE FOCUS
Return from screen saver
WINDOW ACTIVATE
OBJECT GET FOCUS
DataWindows and Events
A DataWindow is a single object within a window. As such, events happen to the DataWindow as a single object (DW COntrol) and not to the individual items that are within the DataWindow object itself. In order to make up for this, there are a number of special events that exist only for DataWindows. These events are not quite the same as those of other Window objects and therefore must be considered on their own.
Consider the following scenario:
The User Clicks on a field in a data window, keys something, clicks on another field within the data window, keys something and then clicks on a Command Button (outside of the DataWindow). The sequence of DataWindow events is as follows:
DW GET FOCUS
DW CLICKED
DW EDIT CHANGED (once for each keystroke)
DW CLICKED
DW ITEMCHANGED
DW ITEM FOCUS CHANGED
DW EDIT CHANGED (once for each keystroke)
DW LOSE FOCUS
COMMAND BUTTON GET FOCUS
COMMAND BUTTON CLICKED
A number of significant aspects are happening at this time! For example: there was only one get focus and one lose focus event. Only one item changed event occurred (even though two items were changed). A clicked event occurred two times. One edit changed event occurred for every keystroke made within the DataWindow.
If DataWindow edits were behind the two modified fields, only the first field would have been edited. For all intents and purposes, the second field has nothing in it!
Now let us insert the ACCEPTTEXT() function into the command button Clicked script. Now the sequence of events flows as follows:
DW GET FOCUS
DW CLICKED
DW EDIT CHANGED (once for each keystroke)
DW CLICKED
DW ITEMCHANGED
DW ITEM FOCUS CHANGED
DW EDIT CHANGED (once for each keystroke)
DW LOSE FOCUS
COMMAND BUTTON GET FOCUS
COMMAND BUTTON CLICKED
DW ITEMCHANGED
The last item changed event was triggered by the AcceptText ( ) functionality. You might be tempted to put this function in the DataWindow Control's losefocus event script, but this makes it very difficult for a user to cancel a transaction when they can not get past the edit rule!
Events Precedence Table
The following is a table that shows the order of events for each object type:
Objects Events Order Notes
Window
Open 1
Activate 2 Also after closing of
another Window
Key 3 Each Keystroke (not all objects)
CloseQuery 4
Close 5
Deactivate 6
Single Line Edit, Multi Line Edit
Get Focus 1
Modified 2
LoseFocus 3
List Box, Drop Down List Box
GetFocus 1
SelectionChanged 2 When choice made from list
Modified 3
DoubleClicked 4 Only possible when "always show
list box" is active
LoseFocus 5
Static Text, Picture, Picture Button
GetFocus 1
Clicked 2
DoubleClicked 3 Always issues a Clicked event first
LoseFocus 4
Check Box, Command Button, Radio Button
GetFocus 1
Clicked 2
LoseFocus 3
DataWindow
GetFocus 1
Clicked 2
DoubleClicked 3 Always issues a Clicked event first
EditChanged 4 Once for each keystroke
ItemError 5 When item doesn't pass validation
ItemChanged 6 When object loses focus within dw
RowFocusChanged 7
ItemFocusChanged 8
LoseFocus 9
Events Notes
Triggerevent Function
At any time in an application, an event can occur through use of the TRIGGEREVENT() function. This can be a very handy thing to know and use. It can also cause problems if the application is counting on certain events to occur in a certain sequence.
DataWindow Clicked Event
Often, the clicked event in a data window is used to trigger a choice made by the user. In the script for this event it is always a good policy to check that the clicked row value is greater than zero. If the click is made on the borders or white space of a data window, the GETCLICKEDROW function will return a zero.
Although the ItemError! event listed after EditChanged! event under dw events order is a bit confusing, I am
sure it is correct as per the 4 phases of validation:
. edit-changed check
. data-type check (ItemError! fires here...)
. item-changed check
. validation-rule check
***********************************************************
Note: You can not safely predict the event model in PB.Net applications as the object drawing and interaction is outside the application's control in the WPF layer of the O/S. WPF controls all aspects of event handling and even imposes restrictions for the PB.Net application!
***********************************************************
Regards ... Chris