update/reorganize events overview and changed links to it to reflect the fact that it speaks about events in general and not just about handling them
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58712 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -7,28 +7,57 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
@page overview_events Events and Event Handling
|
||||
|
||||
@page overview_eventhandling Event Handling
|
||||
Related classes: wxEvtHandler, wxWindow, wxEvent
|
||||
|
||||
Classes: wxEvtHandler, wxWindow, wxEvent
|
||||
|
||||
@li @ref overview_eventhandling_introduction
|
||||
@li @ref overview_eventhandling_eventtables
|
||||
@li @ref overview_eventhandling_connect
|
||||
@li @ref overview_eventhandling_processing
|
||||
@li @ref overview_eventhandling_propagation
|
||||
@li @ref overview_eventhandling_virtual
|
||||
@li @ref overview_eventhandling_prog
|
||||
@li @ref overview_eventhandling_pluggable
|
||||
@li @ref overview_eventhandling_winid
|
||||
@li @ref overview_eventhandling_custom
|
||||
@li @ref overview_eventhandling_macros
|
||||
@li @ref overview_events_introduction
|
||||
@li @ref overview_events_eventhandling
|
||||
@li @ref overview_events_processing
|
||||
@li @ref overview_events_custom
|
||||
@li @ref overview_events_misc
|
||||
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
@section overview_eventhandling_introduction Introduction
|
||||
@section overview_events_introduction Introduction to Events
|
||||
|
||||
Like with all the other GUI frameworks, the control of flow in wxWidgets
|
||||
applications is event-based: the program normally performs most of its actions
|
||||
in response to the events generated by the user. These events can be triggered
|
||||
by using the input devices (such as keyboard, mouse, joystick) directly or,
|
||||
more commonly, by a standard control which synthesizes such input events into
|
||||
higher level events: for example, a wxButton can generate a click event when
|
||||
the user presses the left mouse button on it and then releases it without
|
||||
pressing @c Esc in the meanwhile. There are also events which don't directly
|
||||
correspond to the user actions, such as wxTimerEvent or wxSocketEvent.
|
||||
|
||||
But in all cases wxWidgets represents these events in a uniform way and allows
|
||||
you to handle them in the same way wherever they originate from. And while the
|
||||
events are normally generated by wxWidgets itself, you can also do this, which
|
||||
is especially useful when using custom events (see @ref overview_events_custom).
|
||||
|
||||
To be more precise, each event is described by:
|
||||
- <em>Event type</em>: this is simply a value of type wxEventType which
|
||||
uniquely identifies the type of the event. For example, clicking on a button,
|
||||
selecting an item from a list box and pressing a key on the keyboard all
|
||||
generate events with different event types.
|
||||
- <em>Event class</em> carried by the event: each event has some information
|
||||
associated with it and this data is represented by an object of a class
|
||||
derived from wxEvent. Events of different types can use the same event class,
|
||||
for example both button click and listbox selection events use wxCommandEvent
|
||||
class (as do all the other simple control events), but the key press event
|
||||
uses wxKeyEvent as the information associated with it is different.
|
||||
- <em>Event source</em>: wxEvent stores the object which generated the event
|
||||
and, for windows, its identifier (see @ref overview_events_winid). As it is
|
||||
common to have more than one object generating events of the same type (e.g. a
|
||||
typical window contains several buttons, all generating the same button click
|
||||
event), checking the event source object or its id allows to distinguish
|
||||
between them.
|
||||
|
||||
|
||||
@section overview_events_eventhandling Event Handling
|
||||
|
||||
There are two principal ways to handle events in wxWidgets. One of them uses
|
||||
<em>event table</em> macros and allows you to define the connection between events
|
||||
@@ -46,10 +75,10 @@ although this is probably sufficiently confusing to be a bad idea.
|
||||
|
||||
But before you make this choice, let us discuss these two ways in more
|
||||
detail. In the next section we provide a short introduction to handling the
|
||||
events using the event tables. Please see @ref overview_eventhandling_connect
|
||||
events using the event tables. Please see @ref overview_events_connect
|
||||
for the discussion of Connect().
|
||||
|
||||
@section overview_eventhandling_eventtables Event Handling with Event Tables
|
||||
@subsection overview_events_eventtables Event Handling with Event Tables
|
||||
|
||||
To use an <em>event table</em> you must first decide in which class you wish to
|
||||
handle the events. The only requirement imposed by wxWidgets is that this class
|
||||
@@ -175,7 +204,7 @@ wxEvent-derived classes in the discussion of each control generating these
|
||||
events.
|
||||
|
||||
|
||||
@section overview_eventhandling_connect Dynamic Event Handling
|
||||
@subsection overview_events_connect Dynamic Event Handling
|
||||
|
||||
As with the event tables, decide in which class you intend to
|
||||
handle the events first and, as before, this class must derive from
|
||||
@@ -284,7 +313,7 @@ need this extra power. On the other hand, event tables are still perfectly fine
|
||||
in simple situations where this extra flexibility is not needed.
|
||||
|
||||
|
||||
@section overview_eventhandling_processing How Events are Processed
|
||||
@section overview_events_processing How Events are Processed
|
||||
|
||||
The previous sections explain how to define event handlers but don't address
|
||||
the question of how exactly wxWidgets finds the handler to call for the
|
||||
@@ -332,12 +361,12 @@ doesn't count as having handled the event and the search continues):
|
||||
The event is passed to the next event handler, if any, in the event handler
|
||||
chain, i.e., the steps (1) to (4) are done for it. This chain can be formed
|
||||
using wxEvtHandler::SetNextHandler():
|
||||
@image html overview_eventhandling_chain.png
|
||||
@image html overview_events_chain.png
|
||||
(referring to the image, if @c A->ProcessEvent is called and it doesn't handle
|
||||
the event, @c B->ProcessEvent will be called and so on...).
|
||||
In the case of wxWindow you can build a stack (implemented using wxEvtHandler
|
||||
double-linked list) using wxWindow::PushEventHandler():
|
||||
@image html overview_eventhandling_winstack.png
|
||||
@image html overview_events_winstack.png
|
||||
(referring to the image, if @c W->ProcessEvent is called, it immediately calls
|
||||
@c A->ProcessEvent; if nor @c A nor @c B handle the event, then the wxWindow
|
||||
itself is used - i.e. the dynamically connected event handlers and static
|
||||
@@ -382,16 +411,15 @@ solution is to only handle the events at the view classes level, and not in the
|
||||
document or document manager classes
|
||||
|
||||
|
||||
@section overview_eventhandling_propagation How Events Propagate Upwards
|
||||
@subsection overview_events_propagation How Events Propagate Upwards
|
||||
|
||||
As mentioned in the previous section, the events of the classes deriving from
|
||||
wxCommandEvent are propagated by default to the parent window if they are not
|
||||
processed in this window itself. But although by default only the command
|
||||
events are propagated like this, other events can be propagated as well because
|
||||
the event handling code uses wxEvent::ShouldPropagate() to check whether an
|
||||
event should be propagated. It is also possible to propagate the event only a
|
||||
limited number of times and not until it is processed (or a top level parent
|
||||
window is reached).
|
||||
As mentioned above, the events of the classes deriving from wxCommandEvent are
|
||||
propagated by default to the parent window if they are not processed in this
|
||||
window itself. But although by default only the command events are propagated
|
||||
like this, other events can be propagated as well because the event handling
|
||||
code uses wxEvent::ShouldPropagate() to check whether an event should be
|
||||
propagated. It is also possible to propagate the event only a limited number of
|
||||
times and not until it is processed (or a top level parent window is reached).
|
||||
|
||||
Finally, there is another additional complication (which, in fact, simplifies
|
||||
life of wxWidgets programmers significantly): when propagating the command
|
||||
@@ -446,118 +474,9 @@ will have to be written that will override ProcessEvent() in order to pass
|
||||
all events (or any selection of them) to the parent window.
|
||||
|
||||
|
||||
@section overview_eventhandling_virtual Event Handlers vs Virtual Methods
|
||||
@section overview_events_custom Custom Event Summary
|
||||
|
||||
It may be noted that wxWidgets' event processing system implements something
|
||||
close to virtual methods in normal C++ in spirit: both of these mechanisms
|
||||
allow you to alter the behaviour of the base class by defining the event handling
|
||||
functions in the derived classes.
|
||||
|
||||
There is however an important difference between the two mechanisms when you
|
||||
want to invoke the default behaviour, as implemented by the base class, from a
|
||||
derived class handler. With the virtual functions, you need to call the base
|
||||
class function directly and you can do it either in the beginning of the
|
||||
derived class handler function (to post-process the event) or at its end (to
|
||||
pre-process the event). With the event handlers, you only have the option of
|
||||
pre-processing the events and in order to still let the default behaviour
|
||||
happen you must call wxEvent::Skip() and @em not call the base class event
|
||||
handler directly. In fact, the event handler probably doesn't even exist in the
|
||||
base class as the default behaviour is often implemented in platform-specific
|
||||
code by the underlying toolkit or OS itself. But even if it does exist at
|
||||
wxWidgets level, it should never be called directly as the event handlers are
|
||||
not part of wxWidgets API and should never be called directly.
|
||||
|
||||
Finally, please notice that the event handlers themselves shouldn't be virtual.
|
||||
They should always be non-virtual and usually private (as there is no need to
|
||||
make them public) methods of a wxEvtHandler-derived class.
|
||||
|
||||
|
||||
@section overview_eventhandling_prog User Generated Events vs Programmatically Generated Events
|
||||
|
||||
While generically wxEvents can be generated both by user
|
||||
actions (e.g., resize of a wxWindow) and by calls to functions
|
||||
(e.g., wxWindow::SetSize), wxWidgets controls normally send wxCommandEvent-derived
|
||||
events only for the user-generated events. The only @b exceptions to this rule are:
|
||||
|
||||
@li wxNotebook::AddPage: No event-free alternatives
|
||||
@li wxNotebook::AdvanceSelection: No event-free alternatives
|
||||
@li wxNotebook::DeletePage: No event-free alternatives
|
||||
@li wxNotebook::SetSelection: Use wxNotebook::ChangeSelection instead, as
|
||||
wxNotebook::SetSelection is deprecated
|
||||
@li wxTreeCtrl::Delete: No event-free alternatives
|
||||
@li wxTreeCtrl::DeleteAllItems: No event-free alternatives
|
||||
@li wxTreeCtrl::EditLabel: No event-free alternatives
|
||||
@li All wxTextCtrl methods
|
||||
|
||||
wxTextCtrl::ChangeValue can be used instead of wxTextCtrl::SetValue but the other
|
||||
functions, such as wxTextCtrl::Replace or wxTextCtrl::WriteText don't have event-free
|
||||
equivalents.
|
||||
|
||||
|
||||
|
||||
@section overview_eventhandling_pluggable Pluggable Event Handlers
|
||||
|
||||
In fact, you don't have to derive a new class from a window class
|
||||
if you don't want to. You can derive a new class from wxEvtHandler instead,
|
||||
defining the appropriate event table, and then call wxWindow::SetEventHandler
|
||||
(or, preferably, wxWindow::PushEventHandler) to make this
|
||||
event handler the object that responds to events. This way, you can avoid
|
||||
a lot of class derivation, and use instances of the same event handler class (but different
|
||||
objects as the same event handler object shouldn't be used more than once) to
|
||||
handle events from instances of different widget classes.
|
||||
|
||||
If you ever have to call a window's event handler
|
||||
manually, use the GetEventHandler function to retrieve the window's event handler and use that
|
||||
to call the member function. By default, GetEventHandler returns a pointer to the window itself
|
||||
unless an application has redirected event handling using SetEventHandler or PushEventHandler.
|
||||
|
||||
One use of PushEventHandler is to temporarily or permanently change the
|
||||
behaviour of the GUI. For example, you might want to invoke a dialog editor
|
||||
in your application that changes aspects of dialog boxes. You can
|
||||
grab all the input for an existing dialog box, and edit it 'in situ',
|
||||
before restoring its behaviour to normal. So even if the application
|
||||
has derived new classes to customize behaviour, your utility can indulge
|
||||
in a spot of body-snatching. It could be a useful technique for on-line
|
||||
tutorials, too, where you take a user through a serious of steps and
|
||||
don't want them to diverge from the lesson. Here, you can examine the events
|
||||
coming from buttons and windows, and if acceptable, pass them through to
|
||||
the original event handler. Use PushEventHandler/PopEventHandler
|
||||
to form a chain of event handlers, where each handler processes a different
|
||||
range of events independently from the other handlers.
|
||||
|
||||
|
||||
|
||||
@section overview_eventhandling_winid Window Identifiers
|
||||
|
||||
Window identifiers are integers, and are used to
|
||||
uniquely determine window identity in the event system (though you can use it
|
||||
for other purposes). In fact, identifiers do not need to be unique
|
||||
across your entire application as long they are unique within the
|
||||
particular context you're interested in, such as a frame and its children. You
|
||||
may use the @c wxID_OK identifier, for example, on any number of dialogs
|
||||
as long as you don't have several within the same dialog.
|
||||
|
||||
If you pass @c wxID_ANY to a window constructor, an identifier will be
|
||||
generated for you automatically by wxWidgets. This is useful when you don't
|
||||
care about the exact identifier either because you're not going to process the
|
||||
events from the control being created or because you process the events
|
||||
from all controls in one place (in which case you should specify @c wxID_ANY
|
||||
in the event table or wxEvtHandler::Connect call
|
||||
as well). The automatically generated identifiers are always negative and so
|
||||
will never conflict with the user-specified identifiers which must be always
|
||||
positive.
|
||||
|
||||
See @ref page_stdevtid for the list of standard identifiers available.
|
||||
You can use wxID_HIGHEST to determine the number above which it is safe to
|
||||
define your own identifiers. Or, you can use identifiers below wxID_LOWEST.
|
||||
Finally, you can allocate identifiers dynamically using wxNewId() function too.
|
||||
If you use wxNewId() consistently in your application, you can be sure that
|
||||
your identifiers don't conflict accidentally.
|
||||
|
||||
|
||||
@section overview_eventhandling_custom Custom Event Summary
|
||||
|
||||
@subsection overview_eventhandling_custom_general General approach
|
||||
@subsection overview_events_custom_general General approach
|
||||
|
||||
Since version 2.2.x of wxWidgets, each event type is identified by an ID
|
||||
given to the event type @e at runtime that makes it possible to add
|
||||
@@ -585,7 +504,7 @@ See also the @ref page_samples_event for an example of code
|
||||
defining and working with the custom event types.
|
||||
|
||||
|
||||
@subsection overview_eventhandling_custom_existing Using Existing Event Classes
|
||||
@subsection overview_events_custom_existing Using Existing Event Classes
|
||||
|
||||
If you just want to use a wxCommandEvent with a new event type, use
|
||||
one of the generic event table macros listed below, without having to define a
|
||||
@@ -629,7 +548,7 @@ void MyWindow::SendEvent()
|
||||
@endcode
|
||||
|
||||
|
||||
@subsection overview_eventhandling_custom_generic Generic Event Table Macros
|
||||
@subsection overview_events_custom_generic Generic Event Table Macros
|
||||
|
||||
@beginTable
|
||||
@row2col{EVT_CUSTOM(event\, id\, func),
|
||||
@@ -653,7 +572,7 @@ void MyWindow::SendEvent()
|
||||
@endTable
|
||||
|
||||
|
||||
@subsection overview_eventhandling_custom_ownclass Defining Your Own Event Class
|
||||
@subsection overview_events_custom_ownclass Defining Your Own Event Class
|
||||
|
||||
Under certain circumstances, you must define your own event
|
||||
class e.g., for sending more complex data from one place to another. Apart
|
||||
@@ -723,17 +642,124 @@ void MyWindow::SendEvent()
|
||||
@endcode
|
||||
|
||||
|
||||
@section overview_eventhandling_macros Event Handling Summary
|
||||
@section overview_events_misc Miscellaneous Notes
|
||||
|
||||
@subsection overview_events_virtual Event Handlers vs Virtual Methods
|
||||
|
||||
It may be noted that wxWidgets' event processing system implements something
|
||||
close to virtual methods in normal C++ in spirit: both of these mechanisms
|
||||
allow you to alter the behaviour of the base class by defining the event handling
|
||||
functions in the derived classes.
|
||||
|
||||
There is however an important difference between the two mechanisms when you
|
||||
want to invoke the default behaviour, as implemented by the base class, from a
|
||||
derived class handler. With the virtual functions, you need to call the base
|
||||
class function directly and you can do it either in the beginning of the
|
||||
derived class handler function (to post-process the event) or at its end (to
|
||||
pre-process the event). With the event handlers, you only have the option of
|
||||
pre-processing the events and in order to still let the default behaviour
|
||||
happen you must call wxEvent::Skip() and @em not call the base class event
|
||||
handler directly. In fact, the event handler probably doesn't even exist in the
|
||||
base class as the default behaviour is often implemented in platform-specific
|
||||
code by the underlying toolkit or OS itself. But even if it does exist at
|
||||
wxWidgets level, it should never be called directly as the event handlers are
|
||||
not part of wxWidgets API and should never be called directly.
|
||||
|
||||
Finally, please notice that the event handlers themselves shouldn't be virtual.
|
||||
They should always be non-virtual and usually private (as there is no need to
|
||||
make them public) methods of a wxEvtHandler-derived class.
|
||||
|
||||
|
||||
@subsection overview_events_prog User Generated Events vs Programmatically Generated Events
|
||||
|
||||
While generically wxEvents can be generated both by user
|
||||
actions (e.g., resize of a wxWindow) and by calls to functions
|
||||
(e.g., wxWindow::SetSize), wxWidgets controls normally send wxCommandEvent-derived
|
||||
events only for the user-generated events. The only @b exceptions to this rule are:
|
||||
|
||||
@li wxNotebook::AddPage: No event-free alternatives
|
||||
@li wxNotebook::AdvanceSelection: No event-free alternatives
|
||||
@li wxNotebook::DeletePage: No event-free alternatives
|
||||
@li wxNotebook::SetSelection: Use wxNotebook::ChangeSelection instead, as
|
||||
wxNotebook::SetSelection is deprecated
|
||||
@li wxTreeCtrl::Delete: No event-free alternatives
|
||||
@li wxTreeCtrl::DeleteAllItems: No event-free alternatives
|
||||
@li wxTreeCtrl::EditLabel: No event-free alternatives
|
||||
@li All wxTextCtrl methods
|
||||
|
||||
wxTextCtrl::ChangeValue can be used instead of wxTextCtrl::SetValue but the other
|
||||
functions, such as wxTextCtrl::Replace or wxTextCtrl::WriteText don't have event-free
|
||||
equivalents.
|
||||
|
||||
|
||||
|
||||
@subsection overview_events_pluggable Pluggable Event Handlers
|
||||
|
||||
<em>TODO: Probably deprecated, Connect() provides a better way to do this</em>
|
||||
|
||||
In fact, you don't have to derive a new class from a window class
|
||||
if you don't want to. You can derive a new class from wxEvtHandler instead,
|
||||
defining the appropriate event table, and then call wxWindow::SetEventHandler
|
||||
(or, preferably, wxWindow::PushEventHandler) to make this
|
||||
event handler the object that responds to events. This way, you can avoid
|
||||
a lot of class derivation, and use instances of the same event handler class (but different
|
||||
objects as the same event handler object shouldn't be used more than once) to
|
||||
handle events from instances of different widget classes.
|
||||
|
||||
If you ever have to call a window's event handler
|
||||
manually, use the GetEventHandler function to retrieve the window's event handler and use that
|
||||
to call the member function. By default, GetEventHandler returns a pointer to the window itself
|
||||
unless an application has redirected event handling using SetEventHandler or PushEventHandler.
|
||||
|
||||
One use of PushEventHandler is to temporarily or permanently change the
|
||||
behaviour of the GUI. For example, you might want to invoke a dialog editor
|
||||
in your application that changes aspects of dialog boxes. You can
|
||||
grab all the input for an existing dialog box, and edit it 'in situ',
|
||||
before restoring its behaviour to normal. So even if the application
|
||||
has derived new classes to customize behaviour, your utility can indulge
|
||||
in a spot of body-snatching. It could be a useful technique for on-line
|
||||
tutorials, too, where you take a user through a serious of steps and
|
||||
don't want them to diverge from the lesson. Here, you can examine the events
|
||||
coming from buttons and windows, and if acceptable, pass them through to
|
||||
the original event handler. Use PushEventHandler/PopEventHandler
|
||||
to form a chain of event handlers, where each handler processes a different
|
||||
range of events independently from the other handlers.
|
||||
|
||||
|
||||
|
||||
@subsection overview_events_winid Window Identifiers
|
||||
|
||||
Window identifiers are integers, and are used to
|
||||
uniquely determine window identity in the event system (though you can use it
|
||||
for other purposes). In fact, identifiers do not need to be unique
|
||||
across your entire application as long they are unique within the
|
||||
particular context you're interested in, such as a frame and its children. You
|
||||
may use the @c wxID_OK identifier, for example, on any number of dialogs
|
||||
as long as you don't have several within the same dialog.
|
||||
|
||||
If you pass @c wxID_ANY to a window constructor, an identifier will be
|
||||
generated for you automatically by wxWidgets. This is useful when you don't
|
||||
care about the exact identifier either because you're not going to process the
|
||||
events from the control being created or because you process the events
|
||||
from all controls in one place (in which case you should specify @c wxID_ANY
|
||||
in the event table or wxEvtHandler::Connect call
|
||||
as well). The automatically generated identifiers are always negative and so
|
||||
will never conflict with the user-specified identifiers which must be always
|
||||
positive.
|
||||
|
||||
See @ref page_stdevtid for the list of standard identifiers available.
|
||||
You can use wxID_HIGHEST to determine the number above which it is safe to
|
||||
define your own identifiers. Or, you can use identifiers below wxID_LOWEST.
|
||||
Finally, you can allocate identifiers dynamically using wxNewId() function too.
|
||||
If you use wxNewId() consistently in your application, you can be sure that
|
||||
your identifiers don't conflict accidentally.
|
||||
|
||||
|
||||
@subsection overview_events_macros Event Handling Summary
|
||||
|
||||
For the full list of event classes, please see the
|
||||
@ref group_class_events "event classes group page".
|
||||
|
||||
|
||||
@todo For all controls, state clearly when calling a member function results in
|
||||
an event being generated and when it doesn't (possibly updating also the
|
||||
'Events generated by the user versus programmatically-generated events'
|
||||
paragraph of the 'Event Handling Overview' with the list of the functions
|
||||
that break the rule).
|
||||
|
||||
*/
|
||||
|
||||
|
Reference in New Issue
Block a user