POSCHANGED - What was Previous Field (OpenInsight Specific)
At 16 MAR 1999 03:23:23PM John G. wrote:
We have a POSCHANGED event in a table which does a lot of processing.
POSCHANGED events are called when a user clicks a field in the table.
Is there any way of knowing what the previous field was. Ie is the user entering the table (eg transaction details) from another field (eg customer number), or from another cell within the table?
Obviously, the processing in the POSCHANGED event will be different.
At 16 MAR 1999 04:50PM Dave Pociu wrote:
Use the PREVSELPOS to find out what the previous position was in the table.
As for what field it was in other than the table, I usually put a hook in GOTFOCUS that calls PREVSELPOS with some way different row/column numbers ( negatives ).
So by just looking at the row/column numbers you can tell if the previous cell was inside the table, or a different control.
Dave
P.S. A long time ago ( 1-2 years) Cam had posted ( maybe in the knowledgebase) source code on how edit table events should be processed optimally. I took the above idea from there as far as I remember.
At 17 MAR 1999 05:51AM Colin Rule wrote:
Some possible methods:
a) on Poschanged place the current cells data into the MISC property as the very last thing you do in the event, and very first thing read this property for the previous value.
b) Use @Recur0-4 for same, but be wary of other screens using the same, or a common variable
c) Use a common for history of values, eg COL*ROW in field 1 and value in field 2, then use locate to know exactly where you have been in the table and what the values were.
At 17 MAR 1999 04:25PM John G wrote:
Thanks,
I had hoped that OI had a property which would tell me where the user was coming from.
John
At 17 MAR 1999 04:32PM Cameron Revelation wrote:
John,
1) On GOTFOCUS and I fake a POSCHANGED so that my POSCHANGED always is notified when entering a cell:
<code> * GotFocus declare subroutine Send_Event, Forward_Event declare function Get_Property Forward_Event(PrevFocusID) Pos=Get_Property(CtrlEntID, "SELPOS") Send_Event(CtrlEntID, "POSCHANGED", Pos, Pos) return 0</code>
2) On LOSTFOCUS and I fake a POSCHANGED so that my POSCHANGED always is notified when leaving a cell:
<code> * LostFocus declare subroutine Send_Event * next column/row are zero to signify lost-focus Send_Event(CtrlEntID, "POSCHANGED", 0, 0) return 1</code>
3) On POSCHANGED, I check the new position, only act if it is different from the old position, and store the new position.
<code> * PosChanged declare subroutine Set_Property, Forward_Event declare function Get_Property CurPos =NextColumn: @fm: NextRow PrevPos=Get_Property(CtrlEntID, "@PREVPOS") if CurPos # PrevPos then if PrevPos and PrevPos then * do leaving cell processing here * ... end if CurPos and CurPos then * do entering cell processing here * ... * update last-processed position Set_Property(CtrlEntID, "@PREVPOS", CurPos) end end if NextColumn and NextRow then Forward_Event(NextColumn, NextRow) end return 0</code>
Hope it helps,
Cameron Purdy
Revelation Software
At 17 MAR 1999 09:19PM John wrote:
Cameron,
Thanks for the code.
Would still be nice to have a property which does all this. Eg:
LAST_FIELD - gives name of field user is coming fromJohn
At 18 MAR 1999 08:40AM Cameron Revelation wrote:
John,
PrevFocusID is passed to GOTFOCUS event, and for an edit table, there is a PREVSELPOS property.
The problem (I digress) is the inability to match GUI events 1:1 with programmable "business" events. So what you have to do is use the GUI events (GOTFOCUS, POSCHANGED and LOSTFOCUS for example) to determine that a "business" event has occurred (user has modified a particular cell that you are interested in).
What is the best way to do this in OI? Take the code I gave you and turn it into promoted events in your application. Create two new events (using Event Designer) called CELLGOTFOCUS and CELLLOSTFOCUS, each taking column and row as a parameter. Have the promoted events send CELLGOTFOCUS and CELLLOSTFOCUS when applicable.
So you end up with what you want, with only a single unit of work … quite powerful.
Cameron Purdy
Revelation Software
At 18 MAR 1999 10:20AM Don Bakke wrote:
Hi Cameron,
Okay, would you mind detailing how new promoted event types (i.e. those that don't have a pre-defined event in OI - like CELLLOSTFOCUS) get handled by OI?
I am guessing that if we create a new event type and if we "Enforce" it this will cause the compile logic to reference this event. So far so good?
Now, how in the world does it know what to pass into the parameters we assign them without a system defined event of the same name? Also, in what order does this event get fired relative to other promoted events? Won't that make a difference in some cases?
Or am I missing the point altogether? I noticed in your last post that you suggested the promoted events send CELLGOTFOCUS and CELLLOSTFOCUS. This seems to tell me that what you are implying is that these event will never get fired unless explicitely requested by another event using Send_Event. Is this the more accurate picture?
Thanks,
dbakke@srpcs.com
At 18 MAR 1999 12:29PM Cameron Revelation wrote:
Hi Don,
Okay, would you mind detailing how new promoted event types (i.e. those that don't have a pre-defined event in OI - like CELLLOSTFOCUS) get handled by OI?
Let's first distinguish between OpenInsight and OpenEngine at a very technical level:
1) OpenInsight interfaces with the Windows API to provide GUI and receive notifications from Windows in the form of Windows messages. OpenInsight transfers a select few of the billions of notifications to OpenEngine via REVCAPI or (in the case of a dialog) as a response to a blocking question asked by OpenEngine to OpenInsight. When using REVCAPI, for example, OpenInsight instructs the engine to RUN RUN_EVENT and passes the event name and any necessary event parameters as part of the "command string".
2) OpenEngine actually executes the event code provided by the developer (or the system events, which are just promoted events provided by the developers of the application called SYSPROG). OpenEngine itself has no clue what an event is. Instead, there is an event dispatcher called SEND_EVENT that knows how to find event handlers and in what order to execute them (and when to stop executing the chain of them).
So you can see that ALL events must be sent explicitly by SEND_EVENT … it is just that some of the calls to SEND_EVENT come from OpenInsight. Furthermore, that means that a "pre-defined" event is only pre-defined in that either OpenInsight knows its name (and required parameters) and associates it with a Windows message or that some event handler knows its name (and required parameters).
I am guessing that if we create a new event type and if we "Enforce" it this will cause the compile logic to reference this event. So far so good?
You are correct. The compiler will search for the first event in the chain and specify as part of the compiled form what event that is. (That is why when you promote an event and enforce it, you should recompile all of your forms.)
Now, how in the world does it know what to pass into the parameters we assign them without a system defined event of the same name?
It doesn't. OpenInsight and the SYSPROG event handlers that are part of the base product never call your event.
Also, in what order does this event get fired relative to other promoted events? Won't that make a difference in some cases?
For a particular event, the event chain is constructed from all event handlers that implement (respond to) that event. The "possible links" in the chain are arranged from most-specific to least-specific and are always determined in the same exact manner and order. (Typically, there are only 2-3 elements in a chain out of potentially dozens.)
Or am I missing the point altogether? I noticed in your last post that you suggested the promoted events send CELLGOTFOCUS and CELLLOSTFOCUS. This seems to tell me that what you are implying is that these event will never get fired unless explicitely requested by another event using Send_Event. Is this the more accurate picture?
That is exactly correct. If you want these events fired, you must fire them yourself. (Just like we wrote event handlers so that READ is fired by LOSTFOCUS when the key gets filled in.)
Cameron Purdy
Revelation Software
At 18 MAR 1999 03:30PM John G wrote:
Cameron and Others,
Thanks for the discussion.
I have since discovered that the POSCHANGED event returns two parameters:
NEXTCOLUMN and NEXTROWWhen entering an edit table they are set to
(null). On leaving an edit table they are set to 0. I prefer to do all my event processing in an external program. These 2 parameters are passed to the program which then ignores any calls where NEXTCOLUMN is
or 0.John G
At 19 MAR 1999 01:03PM Don Bakke wrote:
Cameron,
Thanks for firming up my understanding on this. I have, hopefully, one more question:
If developer designed promoted events must be always be called by other events or procedures, what is the advantage of creating a promoted event versus creating a regular function that performs the same way?
dbakke@srpcs.com
At 22 MAR 1999 08:20AM Cameron Revelation wrote:
Don,
If developer designed promoted events must be always be called by other events or procedures, what is the advantage of creating a promoted event versus creating a regular function that performs the same way?
You should differentiate between creating a new event and promoting an event handler:
The benefit of creating the custom event is that once you promote the event that calls it, it works as seamlessly as the other events in the system. If you design it correctly, that means you rarely provide code for the event, but when you need to implement or override the event, it is very easy to do so.
Promoting an event handler lets you take some generic functionality and plug it in to the system at a generic level. Any time that event occurs, your generic code is there to handle it.
Certain things do belong in stored procedures, but when the purpose of something is to re-act, it is a good candidate for an event.
Cameron Purdy
Revelation Software
At 23 MAR 1999 12:23PM Oystein Reigem wrote:
Cameron,
Your code looked so neat I decided to use it in a new form I made, even if it wasn't meant for me.
![]()
But there were problems:
On GOTFOCUS I fake a POSCHANGED so that my POSCHANGED always is notified when entering a cell:…
The user may arrive at the edit table in other ways than a click in a cell. There are two common cases:
- The user clicks somewhere else in the edit table, e.g in the scroll bar. So one has to check CLICKPOS before sending POSCHANGED:
<code></code>
ClickPos=Get_Property( CtrlEntID, "CLICKPOS" )
if ClickPos=3 then
/* clicked in cell */Dum=Send_Event( CtrlEntID, "POSCHANGED", Pos, Pos )end
<code></code>
- The user may tab to the edit table. Unfortunately that makes CLICKPOS is 0, which also can mean the user clicked in the rightmost empty area of the edit table.
How much for an upgrade of your code?
![]()
- Oystein -
At 23 MAR 1999 04:19PM Cameron Revelation wrote:
Oystein,
Are you certain that the code I posted does not work? Regardless of where they click on the edit table or if they tab to it, I believe there is a "current cell" (SELPOS).
Cameron Purdy
Revelation Software
At 24 MAR 1999 07:31AM Oystein Reigem wrote:
Cameron,
You're right about SELPOS. There is always a current cell.
But sometimes the current cell isn't one explicitly chosen by the user. E.g the user arrives the edit table by a click on the scroll bar and the current cell is just what it was from last time the user left the edit table. Or, if there was no last time, the default value of 1:@fm:1.
Yesterday I thought one needed to weed out the "non-explicit" case. But now I see that is not what one would want in general, and that it certainly isn't your code's responsibility.
Your code is unassailable. Thanks!
- Oystein -