X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/04a7eed137acd6ca1f38e4bc7c0570b4035ae6c5..d928f01967cec20e112cc9dde2162b147d8f1433:/docs/doxygen/overviews/eventhandling.h diff --git a/docs/doxygen/overviews/eventhandling.h b/docs/doxygen/overviews/eventhandling.h index 39abbaa3d1..10a1c6543a 100644 --- a/docs/doxygen/overviews/eventhandling.h +++ b/docs/doxygen/overviews/eventhandling.h @@ -3,7 +3,7 @@ // Purpose: topic overview // Author: wxWidgets team // RCS-ID: $Id$ -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// /** @@ -70,18 +70,28 @@ conditions. It also allows the direct binding of events to: @li An ordinary function like a static method or a global function. @li An arbitrary functor like boost::function<>. -The static event tables can only handle -events in the object where they are defined so using Bind<>() is more flexible -than using the event tables. On the other hand, event tables are more succinct -and centralize all event handler bindings in one place. You can either -choose a single approach that you find preferable or freely combine both -methods in your program in different classes or even in one and the same class, -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_events_bind -for the discussion of Bind<>(). +The static event tables can only handle events in the object where they are +defined so using Bind<>() is more flexible than using the event tables. On the +other hand, event tables are more succinct and centralize all event handler +bindings in one place. You can either choose a single approach that you find +preferable or freely combine both methods in your program in different classes +or even in one and the same class, although this is probably sufficiently +confusing to be a bad idea. + +Also notice that most of the existing wxWidgets tutorials and discussions use +the event tables because they historically preceded the apparition of dynamic +event handling in wxWidgets. But this absolutely doesn't mean that using the +event tables is the preferred way: handling events dynamically is better in +several aspects and you should strongly consider doing it if you are just +starting with wxWidgets. On the other hand, you still need to know about the +event tables if only because you are going to see them in many samples and +examples. + +So before you make the choice between static event tables and dynamically +connecting the event handlers, 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_events_bind for the discussion of +Bind<>(). @subsection overview_events_eventtables Event Handling with Event Tables @@ -100,7 +110,7 @@ return information is passed via the argument, which is why it is non-const). You also need to insert a macro @code -DECLARE_EVENT_TABLE() +wxDECLARE_EVENT_TABLE() @endcode somewhere in the class declaration. It doesn't matter where it appears but @@ -131,7 +141,7 @@ private: // obligation to do that; this one is an event handler too: void DoTest(wxCommandEvent& event); - DECLARE_EVENT_TABLE() + wxDECLARE_EVENT_TABLE() }; @endcode @@ -140,12 +150,12 @@ placed in an implementation file. The event table tells wxWidgets how to map events to member functions and in our example it could look like this: @code -BEGIN_EVENT_TABLE(MyFrame, wxFrame) +wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU(wxID_EXIT, MyFrame::OnExit) EVT_MENU(DO_TEST, MyFrame::DoTest) EVT_SIZE(MyFrame::OnSize) EVT_BUTTON(BUTTON1, MyFrame::OnButton1) -END_EVENT_TABLE() +wxEND_EVENT_TABLE() @endcode Notice that you must mention a method you want to use for the event handling in @@ -211,9 +221,11 @@ events. @subsection overview_events_bind Dynamic Event Handling +@see @ref overview_cpp_rtti_disabled + The possibilities of handling events in this way are rather different. Let us start by looking at the syntax: the first obvious difference is that you -need not use DECLARE_EVENT_TABLE() nor BEGIN_EVENT_TABLE() and the +need not use wxDECLARE_EVENT_TABLE() nor wxBEGIN_EVENT_TABLE() and the associated macros. Instead, in any place in your code, but usually in the code of the class defining the handler itself (and definitely not in the global scope as with the event tables), call its Bind<>() method like this: @@ -302,9 +314,12 @@ Now let us describe the semantic differences: -Here are some more examples of how to use different event handlers. +Let us now look at more examples of how to use different event handlers using +the two overloads of Bind() function: first one for the object methods and the +other one for arbitrary functors (callable objects, including simple functions): -You can use a method from a completely different object as an event handler: +In addition to using a method of the object generating the event itself, you +can use a method from a completely different object as an event handler: @code void MyFrameHandler::OnFrameExit( wxCommandEvent & ) @@ -326,6 +341,7 @@ keep in mind that then the lifetime of @c myFrameHandler must be greater than that of @c MyFrame object -- or at least it needs to be unbound before being destroyed. + To use an ordinary function or a static method as an event handler you would write something like this: @@ -414,7 +430,10 @@ in simple situations where this extra flexibility is not needed. 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 -given event. This section describes the algorithm used in detail. +given event. This section describes the algorithm used in detail. Notice that +you may want to run the @ref page_samples_event while reading this section and +look at its code and the output when the button which can be used to test the +event handlers execution order is clicked to understand it better. When an event is received from the windowing system, wxWidgets calls wxEvtHandler::ProcessEvent() on the first event handler object belonging to the @@ -440,11 +459,11 @@ doesn't count as having handled the event and the search continues):
  • - The list of dynamically bind event handlers, i.e., those for which + The list of dynamically bound event handlers, i.e., those for which Bind<>() was called, is consulted. Notice that this is done before checking the static event table entries, so if both a dynamic and a static event handler match the same event, the static one is never going to be - used. + used unless wxEvent::Skip() is called in the dynamic one.
  • @@ -456,21 +475,9 @@ 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_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_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 bind event handlers and static - event table entries of wxWindow are looked as the last possibility, after - all pushed event handlers were tested). - Note however that usually there are no wxEvtHandler chains nor wxWindows stacks - so this step will usually do anything. + chain, i.e., the steps (1) to (4) are done for it. Usually there is no next + event handler so the control passes to the next step but see @ref + overview_events_nexthandler for how the next handler may be defined.
  • @@ -530,7 +537,7 @@ and their parent-child relation are well understood by the programmer while it may be difficult, if not impossible, to track down all the dialogs that may be popped up in a complex program (remember that some are created automatically by wxWidgets). If you need to specify a different behaviour for -some reason, you can use wxWindow::SetExtraStyle(wxWS_EX_BLOCK_EVENTS) +some reason, you can use wxWindow::SetExtraStyle(wxWS_EX_BLOCK_EVENTS) explicitly to prevent the events from being propagated beyond the given window or unset this flag for the dialogs that have it on by default. @@ -549,6 +556,27 @@ will have to be written that will override ProcessEvent() in order to pass all events (or any selection of them) to the parent window. +@subsection overview_events_nexthandler Event Handlers Chain + +The step 4 of the event propagation algorithm checks for the next handler in +the event handler chain. This chain can be formed using +wxEvtHandler::SetNextHandler(): + @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...). + +Additionally, in the case of wxWindow you can build a stack (implemented using +wxEvtHandler double-linked list) using wxWindow::PushEventHandler(): + @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 bind event handlers and static event +table entries of wxWindow are looked as the last possibility, after all pushed +event handlers were tested). + +By default the chain is empty, i.e. there is no next handler. + + @section overview_events_custom Custom Event Summary @subsection overview_events_custom_general General approach @@ -566,6 +594,16 @@ Both strategies are described in details below. See also the @ref page_samples_event for a complete example of code defining and working with the custom event types. +Finally, you will need to generate and post your custom events. +Generation is as simple as instancing your custom event class and initializing +its internal fields. +For posting events to a certain event handler there are two possibilities: +using wxEvtHandler::AddPendingEvent or using wxEvtHandler::QueueEvent. +Basically you will need to use the latter when doing inter-thread communication; +when you use only the main thread you can also safely use the former. +Last, note that there are also two simple global wrapper functions associated +to the two wxEvtHandler mentioned functions: wxPostEvent() and wxQueueEvent(). + @subsection overview_events_custom_existing Using Existing Event Classes @@ -583,16 +621,16 @@ wxDECLARE_EVENT(MY_EVENT, wxCommandEvent); wxDEFINE_EVENT(MY_EVENT, wxCommandEvent); // example of code handling the event with event tables -BEGIN_EVENT_TABLE(MyFrame, wxFrame) +wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_MENU (wxID_EXIT, MyFrame::OnExit) ... EVT_COMMAND (ID_MY_WINDOW, MY_EVENT, MyFrame::OnMyEvent) -END_EVENT_TABLE() +wxEND_EVENT_TABLE() void MyFrame::OnMyEvent(wxCommandEvent& event) { // do something - wxString text = event.GetText(); + wxString text = event.GetString(); } // example of code handling the event with Bind<>(): @@ -608,7 +646,7 @@ void MyWindow::SendEvent() event.SetEventObject(this); // Give it some contents - event.SetText("Hello"); + event.SetString("Hello"); // Do send it ProcessWindowEvent(event); @@ -673,9 +711,9 @@ typedef void (wxEvtHandler::*MyPlotEventFunction)(MyPlotEvent&); // example of code handling the event (you will use one of these methods, not // both, of course): -BEGIN_EVENT_TABLE(MyFrame, wxFrame) +wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) EVT_PLOT(ID_MY_WINDOW, MyFrame::OnPlot) -END_EVENT_TABLE() +wxEND_EVENT_TABLE() MyFrame::MyFrame() {