Function PostAppEvent() Foundation
Places an event in the event queue.
PostAppEvent( <nEvent>, [<mp1>], [<mp2>], [<oXbp>] ) --> lSuccess
The return value of PostAppEvent() is .T. (true) when the event could be written into the event queue, otherwise it is .F. (false).
The function PostAppEvent() allows intervening with the message stream of an event driven application and sending events directly to a specific addressee. PostAppEvent() places events in the event queue, along with the attached message parameters. These events can then be processed by the addressee of the message.
Symbolic constants from the file Appevent.ch are generally used for the event code <nEvent>, but user-defined events can also be used. A user-defined event code is created using the base value (the constant xbeP_User) added to an integer. The message parameter <mp1> and <mp2> may contain any values and are used along with the event code to create the message sent to the addressee <oXbp>. The send occurs using the event queue, meaning it is an asynchronized message transfer when the message containing the event code <nEvent> is placed into the event queue. The addressee of the message only receives the message when it is read from the event queue by the function AppEvent().
If an addressee is specified, the addressee of the message must be an XBase Part. Note that Xbase Parts "understand" only a limited number of messages. If #define constants from the file Appevent.ch are used for the event code <nEvent>, a constant should be selected which is known to be an event processed by the addressee of the message. Otherwise, the addressee does not react or the event is sent on to the window. The event codes recognized by the various Xbase Parts are described in the section on each Xbase Part.
Multithreading issues and GUI
In a GUI application, events are collected in an event queue and retrieved from this queue by the AppEvent() function. If a GUI program is split into multiple threads, it must be emphasized that an event queue has thread-local scope and each thread maintains its own event queue. When an event is posted to a particular Xbase Part (4th parameter <oXbp>), PostAppEvent() places this event in the event queue of the thread the Xbase Part was created in. For example, if thread B executes PostAppEvent() and posts an event to an Xbase Part created in thread A, the event arrives in the event queue of thread A and can only be retrieved from this queue when AppEvent() is executed in thread A. As a result, the event posted in thread B will be processed in thread A, not in thread B.
If a program is not linked with the linker switch /PM:PM, it is a text mode application which has only one event queue. When a text mode application uses multiple threads, they share this queue.
// The example demonstrates using PostAppEvent() for user-defined
// events. The event codes are defined as #define constants with
// 'xbeP_User' as the base value. In the example, the position
// for a box can be determined by mouse clicks and it is then
// displayed. PostAppEvent() places the function values Date()
// and Time() as message parameters into the event queue. The
// example uses no addressee for the message, but illustrates
// the general mechanism for transmitting a message using the
// event queue.
#include "Appevent.ch"
#define xbeU_DrawBox xbeP_User + 1
#define xbeU_Quit xbeP_User + 2
PROCEDURE Main
LOCAL nEvent := 0, mp1, mp2
CLEAR
@ 0,0 SAY " Output box | QUIT"
SetMouse(.T.) // activate mouse
// infinite loop
DO WHILE .T.
nEvent := AppEvent( @mp1, @mp2,, 0 )
DO CASE
CASE nEvent == xbeU_DrawBox // mp1=Date(), mp2=Time()
DrawBox( mp1, mp2 ) // from PostAppEvent()
CASE nEvent == xbeU_Quit
QUIT
CASE nEvent < xbeB_Event
@ MaxRow(), 0
?? "Key code is", nEvent
CASE nEvent == xbeM_LbClick // click of left mouse
// button
IF mp1[1] == 0 .AND. mp1[2] <= 21 // click in first row
IF mp1[2] <= 15
PostAppEvent( xbeU_DrawBox, Date(), Time() )
ELSE
PostAppEvent( xbeU_Quit )
ENDIF
ELSE
@ mp1[1], mp1[2] SAY "No choice made"
ENDIF
ENDCASE
ENDDO
RETURN
*********************************
PROCEDURE DrawBox( dDate, cTime )
LOCAL nEvent := 0, mp1, mp2
LOCAL nTop, nLeft, nBottom, nRight
SAVE SCREEN
@ 0, 0 SAY "Click upper left corner of the box"
DO WHILE nEvent <> xbeM_LbClick // establish coordinates
nEvent := AppEvent( @mp1, @mp2,, 0 )
ENDDO
nTop := mp1[1]
nLeft := mp1[2]
nEvent := 0
@ nTop, nLeft SAY "Click lower right corner of the box"
DO WHILE nEvent <> xbeM_LbClick
nEvent := AppEvent( @mp1, @mp2,, 0 )
IF nEvent == xbeM_LbClick .AND.; // incorrect coordinates
( mp1[1] <= nTop .OR. mp1[2] <= nLeft )
Tone(1000,1)
nEvent := 0
ENDIF
ENDDO
nBottom := mp1[1]
nRight := mp1[2]
RESTORE SCREEN
@ nTop, nLeft TO nBottom, nRight
@ nTop+1,nLeft+1 SAY "Date:"
?? dDate
@ nTop+2,nLeft+1 SAY " Time:"
?? cTime
RETURN
// In the example, 26 pushbuttons and a multiple line entry field
// are created. Each pushbutton displays a letter of the
// alphabet. When a pushbutton is pressed, it sends a message
// with the ASCII code of a letter to the input field.
// The input field processes the applicable event and
// displays the letter of the pushbutton in the edit buffer.
#include "Appevent.ch"
PROCEDURE Main
LOCAL nEvent, mp1, mp2, oXbp, oBtn, oMLE, bActivate, i
SetMouse( .T. ) // process mouse events
SetColor( "N/W" ) // fill window
CLS // pale gray
// multiple line entry field
oMLE := XbpMLE():new(,, {20,50}, {600,240} )
oMLE:create()
oMLE:setData( "Xbase++ - multiple line entry field" )
// Activate code block for the pushbuttons:
// In the code block a message is posted to the MLE.
// oBtn is the pushbutton which was pressed.
//
bActivate := ;
{|mp1,mp2,oBtn| PostAppEvent( xbeP_Keyboard, ;
Asc( oBtn:caption ),, oMLE ) }
FOR i:=1 TO 26 // create 26 pushbuttons
oBtn := XbpPushButton():new(,, {23*i, 350}, {20, 32} )
oBtn:caption := Chr(64+i) // each pushbutton places
oBtn:activate := bActivate // a letter in the
oBtn:pointerFocus := .F. // event queue
oBtn:create()
NEXT
nEvent := 0 // process events
DO WHILE nEvent <> xbeP_Close
nEvent := AppEvent( @mp1, @mp2, @oXbp, 0 )
IF nEvent == xbeK_ESC
EXIT
ELSEIF oXbp <> NIL
oXbp:handleEvent( nEvent, mp1, mp2, oXbp )
ENDIF
ENDDO
RETURN
If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.