Function AppEvent() Foundation

Reads the next event and removes it from the event queue.

Syntax
AppEvent( [@<mp1>], [@<mp2>], [@<oXbp>], [<nTimeOut>] ) --> nEvent
Parameters
<mp1>
The first message parameter of the event is assigned to <mp1>within AppEvent(). The variable is optional, but if it is passed it must always be passed to AppEvent() by reference.
<mp2>
The second message parameter of the event is assigned to <mp2>within AppEvent(). The variable is optional, but if it is passed it must always be passed to AppEvent() by reference.
<oXbp>
The addressee of the message (event) is assigned to the variable <oXbp> within AppEvent(). This parameter is also optional but is needed in connection with Xbase Parts. As an example, it might indicate an Xbase Part that was clicked with the mouse.
<nTimeOut>
<nTimeOut> is an integer numeric value indicating a time interval in 1/100 seconds. When no event is found in the queue, the function AppEvent() waits <nTimeOut> times 0.01 seconds before execution of the program continues. The default value is zero which causes AppEvent() to wait until an event is found in the queue.
Return

The return value of AppEvent() is a numeric code identifying the event removed from the queue. The #include file Appevent.ch contains #define constants corresponding to the integer numeric event codes. If a value > 0 is passed for <nTimeOut> and this time elapses with no event being created, the return value is xbe_None. In this case, all parameters passed by reference contain NIL.

Description

The function AppEvent() reads and removes events from the event queue. Events are generally caused by the user by a key stroke or a mouse click. Each event is identified by a numeric code which is returned from AppEvent(). Symbolic constants for the event codes are defined in the #include file Appevent.ch. The names for these #define constants are in mixed case and always begin with the three letters xbe(an abbreviation for xbase event). This is generally followed by one or more uppercase letters which identify the category for an event and an underscore.

Examples for #define constants and categories for events
Category Prefix Constant
No event xbe_ xbe_None
Keyboard event *) xbeK_ xbeK_RETURN
Mouse event xbeM_ xbeM_LbDown
Generic Xbase Part event xbeP_ xbeP_Activate
Xbase Part-specific event (example: XbpSLE class) xbeSLE_ xbeSLE_Overflow
  1. Text and hybrid mode applications only, see below

Apart from the unique event identifier, additional information is generally required to fully describe an event. This information is assigned to the message parameters <mp1> and <mp2>. These two arguments must always be passed to the function AppEvent() by reference. After the function returns, the message parameters can hold event specific values. For example, with mouse events <mp1> contains the position of the mouse pointer. For other events, one or both message parameters can contain the value NIL or complex values like arrays or objects.

AppEvent() in text mode (VIO) applications

If an Xbase++ application is linked in VIO mode, AppEvent() returns only events in the keyboard (xbeK_) and mouse (xbeM_) event categories. To differentiate between keyboard and mouse events, an event code can be tested against the special #define constant xbeB_Event (base event). Event codes identifying a key stroke are guaranteed to be less than xbeB_Event. All other events, including those identifying user-defined events, are identified by event codes higher than xbeB_Event. In text mode, the message parameters <mp1> and <mp2> are optional and have meaning only with mouse events or user-defined events.

In VIO mode the text mode terminal is the only primary event source. For this reason, specifying the parameter <oXbp> is normally not required. See the example below for illustration. For more information on user-defined events, see the function PostAppEvent().

For mouse events to be registered in a VIO application, the function call SetMouse(.T.) must occur before the function AppEvent() is called.

AppEvent in GUI applications

For Xbase++ applications linked in PM mode, AppEvent() processes the whole range of events supported by the Xbase++ runtime system. In this mode, there may be several event sources. Each object in the application's user interface can generate events depending on user interaction. A mouse button may be clicked on a push button as well as on an entry field, for example. For this reason, the third parameter <oXbp> should always be specified in the call of AppEvent() when using Xbase Parts. Like <mp1> and <mp2>, this parameter must be passed by reference. It receives the Xbase Part (object) that is to process the event. After retrieving an event from the queue, the event code and corresponding message parameters should be passed on to the object's :handleEvent()method for further processing (see example below).

In full-GUI applications, AppEvent() does not return key codes from the keyboard event category (xbeK_ #define constants). Instead, key stroke are returned as xbeP_Keyboard events, with the key code given in the first message parameter (<mp1>).

AppEvent in hybrid mode applications

In so-called hybrid mode applications, an XbpCrt window is used as the terminal window. XbpCrt windows allow to mix text mode commands, such as @...GET with GUI elements (Xbase Parts). This allows a step-by-step migration of legacy application code. In hybrid mode, the full range of events is available to the Xbase++ application via AppEvent(). As long as only the hybrid mode terminal window is used, parameters <mp1>, <mp2>, <oXbp> and <nTimeOut> are optional. However, if Xbase Parts such as XbpPushButton objects are added to the application, all three parameters should be specified and must be passed by reference to AppEvent().

For compatibility, the event codes used in text mode (VIO) are also supported in hybrid mode. If a key is pressed in a hybrid mode terminal, AppEvent() returns both a compatible event code (using an xbeK_ #define) as well as a generic keyboard event (xbeP_Keyboard event code).

For mouse events to be registered in a hybrid mode terminal window (XbpCrt object), the function call SetMouse(.T.) must occur before the call to the function AppEvent().

Multithreading issuesAll events are stored in a so-called event queue and AppEvent() retrieves events from this queue. If a program uses multiple threads, it is important to know that event queues have thread-local scope. When Xbase Parts are created in different threads, they are retrieved from different event queues by AppEvent() (3rd parameter oXbp). As a result, each thread that creates an Xbase Part must call AppEvent() so that events for this Xbase Part can be processed.

Examples
AppEvent() and message parameters

// The example shows event codes and the message 
// parameters of the function AppEvent(). The program displays 
// the return value of AppEvent() and the values of the message 
// parameters on the screen. It is terminated by a click of 
// the right mouse button. AppEvent() is used in a way 
// compatible with text and hybrid mode. 

#include "Appevent.ch" 
#xtranslate GUI_EVENT( <nEvent> ) => (<nEvent> > xbeB_Event) 

PROCEDURE Main 
   LOCAL nEvent := 0, mp1, mp2 

   CLEAR 
   @ 0,0 SAY "Press right mouse button to terminate" 
   SetMouse(.T.) 

   DO WHILE nEvent <> xbeM_RbDown 
      nEvent := AppEvent( @mp1, @mp2, , 0) 

      IF GUI_EVENT( nEvent ) 
         @ 2, 0 SAY "GUI event: " + PadR( Var2Char( nEvent ), 10 ) 
         @ 3, 0 SAY "mp1:       " + PadR( Var2Char( mp1 ), 10 ) 
         @ 4, 0 SAY "mp2:       " + PadR( Var2Char( mp2 ), 10 ) 
      ELSE 
         @ 6, 0 SAY "KEY event: " + PadR( Var2Char( nEvent ), 10 ) 
         @ 7, 0 SAY "mp1:       " + PadR( Var2Char( mp1 ), 10 ) 
         @ 8, 0 SAY "mp2:       " + PadR( Var2Char( mp2 ), 10 ) 
      ENDIF 
   ENDDO 

RETURN 
AppEvent() and Xbase Parts

// In the example, a simple event loop is illustrated 
// which directs the events to three pushbuttons (Xbase 
// Parts). Note that all three parameters are specified 
// in the call to AppEvent(). 

#include "Appevent.ch" 

PROCEDURE Main 
   LOCAL oBtn, nEvent, mp1, mp2, oXbp 

   SetColor("N/W")                  // fill window with pale gray 
   CLS 

   // create pushbutton to output text 
   // 
   oBtn := XbpPushButton():new(,, {25, 5}, {80, 30} ) 
   oBtn:caption  := " Next " 
   oBtn:activate := {|| QOut( "Button NEXT" ) } 
   oBtn:create() 
   oBtn:show() 

   // create pushbutton to output text 
   // 
   oBtn := XbpPushButton():new(,, {120, 5}, {80, 30} ) 
   oBtn:caption  := " Previous " 
   oBtn:activate := {|| QOut( "Button PREVIOUS" ) } 
   oBtn:create() 
   oBtn:show() 

   // create pushbutton to terminate program 
   // 
   oBtn := XbpPushButton():new(,, {500, 5}, {100, 30} ) 
   oBtn:caption  := " End " 
   oBtn:activate := {|| PostAppEvent( xbeP_Close ) } 
   oBtn:create() 
   oBtn:show() 

   SetMouse( .T. )                  // activate mouse events 
   nEvent := xbe_None 
                                    // terminate program with the 
   DO WHILE nEvent <> xbeP_Close    // event xbeP_Close 
      nEvent := AppEvent( @mp1, @mp2, @oXbp, 0 ) 

      oXbp:handleEvent( nEvent, mp1, mp2 ) 
   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.