Function PostAppEvent() Foundation

Places an event in the event queue.

Syntax
PostAppEvent( <nEvent>, [<mp1>], [<mp2>], [<oXbp>] ) --> lSuccess
Parameters
<nEvent>
<nEvent> is the numeric event code for the event which is to be placed in the event queue. Symbolic constants defined in the #include file Appevent.ch can be used for <nEvent>.
<mp1>
<mp1> is an optional expression whose value is assigned to the first message parameter of the function AppEvent() when the event is read from the event queue. If <mp1> is not specified, the first message parameter of AppEvent() will contain the value NIL.
<mp2>
<mp2> is an optional expression whose value is assigned to the second message parameter of the function AppEvent() when the event is read from the event queue. If <mp2> is not specified, the second message parameter of AppEvent() will contain the value NIL.
<oXbp>
The parameter <oXbp> is also optional. If it is specified, it must be a reference to an Xbase Part (object) as the addressee. The Xbase Part is assigned to the third parameter of the function AppEvent() when the event is read from the event queue. If <oXbp> is not specified, the third parameter of AppEvent() references the return value of SetAppWindow().
Return

The return value of PostAppEvent() is .T. (true) when the event could be written into the event queue, otherwise it is .F. (false).

Description

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.

Examples
User-defined events

// 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 
Send messages to Xbase Parts

// 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 

Feedback

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.