Function AppEvent() Foundation
Reads the next event and removes it from the event queue.
AppEvent( [@<mp1>], [@<mp2>], [@<oXbp>], [<nTimeOut>] ) --> nEvent
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.
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.
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 |
|
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().
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).
Multithreading issues All 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.
// 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
// 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
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.