| 1 | ///////////////////////////////////////////////////////////////////////////// |
| 2 | // Name: eventhandling.h |
| 3 | // Purpose: topic overview |
| 4 | // Author: wxWidgets team |
| 5 | // RCS-ID: $Id$ |
| 6 | // Licence: wxWindows licence |
| 7 | ///////////////////////////////////////////////////////////////////////////// |
| 8 | |
| 9 | /** |
| 10 | |
| 11 | @page overview_events Events and Event Handling |
| 12 | |
| 13 | Related classes: wxEvtHandler, wxWindow, wxEvent |
| 14 | |
| 15 | @li @ref overview_events_introduction |
| 16 | @li @ref overview_events_eventhandling |
| 17 | @li @ref overview_events_processing |
| 18 | @li @ref overview_events_custom |
| 19 | @li @ref overview_events_misc |
| 20 | |
| 21 | |
| 22 | <hr> |
| 23 | |
| 24 | |
| 25 | @section overview_events_introduction Introduction to Events |
| 26 | |
| 27 | Like with all the other GUI frameworks, the control of flow in wxWidgets |
| 28 | applications is event-based: the program normally performs most of its actions |
| 29 | in response to the events generated by the user. These events can be triggered |
| 30 | by using the input devices (such as keyboard, mouse, joystick) directly or, |
| 31 | more commonly, by a standard control which synthesizes such input events into |
| 32 | higher level events: for example, a wxButton can generate a click event when |
| 33 | the user presses the left mouse button on it and then releases it without |
| 34 | pressing @c Esc in the meanwhile. There are also events which don't directly |
| 35 | correspond to the user actions, such as wxTimerEvent or wxSocketEvent. |
| 36 | |
| 37 | But in all cases wxWidgets represents these events in a uniform way and allows |
| 38 | you to handle them in the same way wherever they originate from. And while the |
| 39 | events are normally generated by wxWidgets itself, you can also do this, which |
| 40 | is especially useful when using custom events (see @ref overview_events_custom). |
| 41 | |
| 42 | To be more precise, each event is described by: |
| 43 | - <em>Event type</em>: this is simply a value of type wxEventType which |
| 44 | uniquely identifies the type of the event. For example, clicking on a button, |
| 45 | selecting an item from a list box and pressing a key on the keyboard all |
| 46 | generate events with different event types. |
| 47 | - <em>Event class</em> carried by the event: each event has some information |
| 48 | associated with it and this data is represented by an object of a class |
| 49 | derived from wxEvent. Events of different types can use the same event class, |
| 50 | for example both button click and listbox selection events use wxCommandEvent |
| 51 | class (as do all the other simple control events), but the key press event |
| 52 | uses wxKeyEvent as the information associated with it is different. |
| 53 | - <em>Event source</em>: wxEvent stores the object which generated the event |
| 54 | and, for windows, its identifier (see @ref overview_events_winid). As it is |
| 55 | common to have more than one object generating events of the same type (e.g. a |
| 56 | typical window contains several buttons, all generating the same button click |
| 57 | event), checking the event source object or its id allows to distinguish |
| 58 | between them. |
| 59 | |
| 60 | |
| 61 | @section overview_events_eventhandling Event Handling |
| 62 | |
| 63 | There are two principal ways to handle events in wxWidgets. One of them uses |
| 64 | <em>event table</em> macros and allows you to define the binding between events |
| 65 | and their handlers only statically, i.e., during program compilation. The other |
| 66 | one uses wxEvtHandler::Bind<>() call and can be used to bind and |
| 67 | unbind, the handlers dynamically, i.e. during run-time depending on some |
| 68 | conditions. It also allows the direct binding of events to: |
| 69 | @li A handler method in another object. |
| 70 | @li An ordinary function like a static method or a global function. |
| 71 | @li An arbitrary functor like boost::function<>. |
| 72 | |
| 73 | The static event tables can only handle events in the object where they are |
| 74 | defined so using Bind<>() is more flexible than using the event tables. On the |
| 75 | other hand, event tables are more succinct and centralize all event handler |
| 76 | bindings in one place. You can either choose a single approach that you find |
| 77 | preferable or freely combine both methods in your program in different classes |
| 78 | or even in one and the same class, although this is probably sufficiently |
| 79 | confusing to be a bad idea. |
| 80 | |
| 81 | Also notice that most of the existing wxWidgets tutorials and discussions use |
| 82 | the event tables because they historically preceded the apparition of dynamic |
| 83 | event handling in wxWidgets. But this absolutely doesn't mean that using the |
| 84 | event tables is the preferred way: handling events dynamically is better in |
| 85 | several aspects and you should strongly consider doing it if you are just |
| 86 | starting with wxWidgets. On the other hand, you still need to know about the |
| 87 | event tables if only because you are going to see them in many samples and |
| 88 | examples. |
| 89 | |
| 90 | So before you make the choice between static event tables and dynamically |
| 91 | connecting the event handlers, let us discuss these two ways in more detail. In |
| 92 | the next section we provide a short introduction to handling the events using |
| 93 | the event tables. Please see @ref overview_events_bind for the discussion of |
| 94 | Bind<>(). |
| 95 | |
| 96 | @subsection overview_events_eventtables Event Handling with Event Tables |
| 97 | |
| 98 | To use an <em>event table</em> you must first decide in which class you wish to |
| 99 | handle the events. The only requirement imposed by wxWidgets is that this class |
| 100 | must derive from wxEvtHandler and so, considering that wxWindow derives from |
| 101 | it, any classes representing windows can handle events. Simple events such as |
| 102 | menu commands are usually processed at the level of a top-level window |
| 103 | containing the menu, so let's suppose that you need to handle some events in @c |
| 104 | MyFrame class deriving from wxFrame. |
| 105 | |
| 106 | First define one or more <em>event handlers</em>. They |
| 107 | are just simple methods of the class that take as a parameter a |
| 108 | reference to an object of a wxEvent-derived class and have no return value (any |
| 109 | return information is passed via the argument, which is why it is non-const). |
| 110 | You also need to insert a macro |
| 111 | |
| 112 | @code |
| 113 | wxDECLARE_EVENT_TABLE() |
| 114 | @endcode |
| 115 | |
| 116 | somewhere in the class declaration. It doesn't matter where it appears but |
| 117 | it's customary to put it at the end because the macro changes the access |
| 118 | type internally so it's safest if nothing follows it. The |
| 119 | full class declaration might look like this: |
| 120 | |
| 121 | @code |
| 122 | class MyFrame : public wxFrame |
| 123 | { |
| 124 | public: |
| 125 | MyFrame(...) : wxFrame(...) { } |
| 126 | |
| 127 | ... |
| 128 | |
| 129 | protected: |
| 130 | int m_whatever; |
| 131 | |
| 132 | private: |
| 133 | // Notice that as the event handlers normally are not called from outside |
| 134 | // the class, they normally are private. In particular they don't need |
| 135 | // to be public. |
| 136 | void OnExit(wxCommandEvent& event); |
| 137 | void OnButton1(wxCommandEvent& event); |
| 138 | void OnSize(wxSizeEvent& event); |
| 139 | |
| 140 | // it's common to call the event handlers OnSomething() but there is no |
| 141 | // obligation to do that; this one is an event handler too: |
| 142 | void DoTest(wxCommandEvent& event); |
| 143 | |
| 144 | wxDECLARE_EVENT_TABLE() |
| 145 | }; |
| 146 | @endcode |
| 147 | |
| 148 | Next the event table must be defined and, as with any definition, it must be |
| 149 | placed in an implementation file. The event table tells wxWidgets how to map |
| 150 | events to member functions and in our example it could look like this: |
| 151 | |
| 152 | @code |
| 153 | wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) |
| 154 | EVT_MENU(wxID_EXIT, MyFrame::OnExit) |
| 155 | EVT_MENU(DO_TEST, MyFrame::DoTest) |
| 156 | EVT_SIZE(MyFrame::OnSize) |
| 157 | EVT_BUTTON(BUTTON1, MyFrame::OnButton1) |
| 158 | wxEND_EVENT_TABLE() |
| 159 | @endcode |
| 160 | |
| 161 | Notice that you must mention a method you want to use for the event handling in |
| 162 | the event table definition; just defining it in MyFrame class is @e not enough. |
| 163 | |
| 164 | Let us now look at the details of this definition: the first line means that we |
| 165 | are defining the event table for MyFrame class and that its base class is |
| 166 | wxFrame, so events not processed by MyFrame will, by default, be handled by |
| 167 | wxFrame. The next four lines define bindings of individual events to their |
| 168 | handlers: the first two of them map menu commands from the items with the |
| 169 | identifiers specified as the first macro parameter to two different member |
| 170 | functions. In the next one, @c EVT_SIZE means that any changes in the size of |
| 171 | the frame will result in calling OnSize() method. Note that this macro doesn't |
| 172 | need a window identifier, since normally you are only interested in the current |
| 173 | window's size events. |
| 174 | |
| 175 | The @c EVT_BUTTON macro demonstrates that the originating event does not have to |
| 176 | come from the window class implementing the event table -- if the event source |
| 177 | is a button within a panel within a frame, this will still work, because event |
| 178 | tables are searched up through the hierarchy of windows for the command events. |
| 179 | (But only command events, so you can't catch mouse move events in a child |
| 180 | control in the parent window in the same way because wxMouseEvent doesn't |
| 181 | derive from wxCommandEvent. See below for how you can do it.) In this case, the |
| 182 | button's event table will be searched, then the parent panel's, then the |
| 183 | frame's. |
| 184 | |
| 185 | Finally, you need to implement the event handlers. As mentioned before, all |
| 186 | event handlers take a wxEvent-derived argument whose exact class differs |
| 187 | according to the type of event and the class of the originating window. For |
| 188 | size events, wxSizeEvent is used. For menu commands and most control commands |
| 189 | (such as button presses), wxCommandEvent is used. When controls get more |
| 190 | complicated, more specific wxCommandEvent-derived event classes providing |
| 191 | additional control-specific information can be used, such as wxTreeEvent for |
| 192 | events from wxTreeCtrl windows. |
| 193 | |
| 194 | In the simplest possible case an event handler may not use the @c event |
| 195 | parameter at all. For example, |
| 196 | |
| 197 | @code |
| 198 | void MyFrame::OnExit(wxCommandEvent& WXUNUSED(event)) |
| 199 | { |
| 200 | // when the user selects "Exit" from the menu we should close |
| 201 | Close(true); |
| 202 | } |
| 203 | @endcode |
| 204 | |
| 205 | In other cases you may need some information carried by the @c event argument, |
| 206 | as in: |
| 207 | |
| 208 | @code |
| 209 | void MyFrame::OnSize(wxSizeEvent& event) |
| 210 | { |
| 211 | wxSize size = event.GetSize(); |
| 212 | |
| 213 | ... update the frame using the new size ... |
| 214 | } |
| 215 | @endcode |
| 216 | |
| 217 | You will find the details about the event table macros and the corresponding |
| 218 | wxEvent-derived classes in the discussion of each control generating these |
| 219 | events. |
| 220 | |
| 221 | |
| 222 | @subsection overview_events_bind Dynamic Event Handling |
| 223 | |
| 224 | @see @ref overview_cpp_rtti_disabled |
| 225 | |
| 226 | The possibilities of handling events in this way are rather different. |
| 227 | Let us start by looking at the syntax: the first obvious difference is that you |
| 228 | need not use wxDECLARE_EVENT_TABLE() nor wxBEGIN_EVENT_TABLE() and the |
| 229 | associated macros. Instead, in any place in your code, but usually in |
| 230 | the code of the class defining the handler itself (and definitely not in the |
| 231 | global scope as with the event tables), call its Bind<>() method like this: |
| 232 | |
| 233 | @code |
| 234 | MyFrame::MyFrame(...) |
| 235 | { |
| 236 | Bind(wxEVT_COMMAND_MENU_SELECTED, &MyFrame::OnExit, this, wxID_EXIT); |
| 237 | } |
| 238 | @endcode |
| 239 | |
| 240 | Note that @c this pointer must be specified here. |
| 241 | |
| 242 | Now let us describe the semantic differences: |
| 243 | <ul> |
| 244 | <li> |
| 245 | Event handlers can be bound at any moment. For example, it's possible |
| 246 | to do some initialization first and only bind the handlers if and when |
| 247 | it succeeds. This can avoid the need to test that the object was properly |
| 248 | initialized in the event handlers themselves. With Bind<>() they |
| 249 | simply won't be called if it wasn't correctly initialized. |
| 250 | </li> |
| 251 | |
| 252 | <li> |
| 253 | As a slight extension of the above, the handlers can also be unbound at |
| 254 | any time with Unbind<>() (and maybe rebound later). Of course, |
| 255 | it's also possible to emulate this behaviour with the classic |
| 256 | static (i.e., bound via event tables) handlers by using an internal |
| 257 | flag indicating whether the handler is currently enabled and returning |
| 258 | from it if it isn't, but using dynamically bind handlers requires |
| 259 | less code and is also usually more clear. |
| 260 | </li> |
| 261 | |
| 262 | <li> |
| 263 | Almost last but very, very far from least is the increased flexibility |
| 264 | which allows to bind an event to: |
| 265 | @li A method in another object. |
| 266 | @li An ordinary function like a static method or a global function. |
| 267 | @li An arbitrary functor like boost::function<>. |
| 268 | |
| 269 | This is impossible to do with the event tables because it is not |
| 270 | possible to specify these handlers to dispatch the event to, so it |
| 271 | necessarily needs to be sent to the same object which generated the |
| 272 | event. Not so with Bind<>() which can be used to specify these handlers |
| 273 | which will handle the event. To give a quick example, a common question |
| 274 | is how to receive the mouse movement events happening when the mouse is |
| 275 | in one of the frame children in the frame itself. Doing it in a naive |
| 276 | way doesn't work: |
| 277 | <ul> |
| 278 | <li> |
| 279 | A @c EVT_LEAVE_WINDOW(MyFrame::OnMouseLeave) line in the frame |
| 280 | event table has no effect as mouse move (including entering and |
| 281 | leaving) events are not propagated up to the parent window |
| 282 | (at least not by default). |
| 283 | </li> |
| 284 | |
| 285 | <li> |
| 286 | Putting the same line in a child event table will crash during |
| 287 | run-time because the MyFrame method will be called on a wrong |
| 288 | object -- it's easy to convince oneself that the only object |
| 289 | that can be used here is the pointer to the child, as |
| 290 | wxWidgets has nothing else. But calling a frame method with the |
| 291 | child window pointer instead of the pointer to the frame is, of |
| 292 | course, disastrous. |
| 293 | </li> |
| 294 | </ul> |
| 295 | |
| 296 | However writing |
| 297 | @code |
| 298 | MyFrame::MyFrame(...) |
| 299 | { |
| 300 | m_child->Bind(wxEVT_LEAVE_WINDOW, &MyFrame::OnMouseLeave, this); |
| 301 | } |
| 302 | @endcode |
| 303 | will work exactly as expected. Note that you can get the object that |
| 304 | generated the event -- and that is not the same as the frame -- via |
| 305 | wxEvent::GetEventObject() method of @c event argument passed to the |
| 306 | event handler. |
| 307 | </li> |
| 308 | |
| 309 | <li> |
| 310 | Really last point is the consequence of the previous one: because of |
| 311 | increased flexibility of Bind(), it is also safer as it is impossible |
| 312 | to accidentally use a method of another class. Instead of run-time |
| 313 | crashes you will get compilation errors in this case when using Bind(). |
| 314 | </li> |
| 315 | </ul> |
| 316 | |
| 317 | Let us now look at more examples of how to use different event handlers using |
| 318 | the two overloads of Bind() function: first one for the object methods and the |
| 319 | other one for arbitrary functors (callable objects, including simple functions): |
| 320 | |
| 321 | In addition to using a method of the object generating the event itself, you |
| 322 | can use a method from a completely different object as an event handler: |
| 323 | |
| 324 | @code |
| 325 | void MyFrameHandler::OnFrameExit( wxCommandEvent & ) |
| 326 | { |
| 327 | // Do something useful. |
| 328 | } |
| 329 | |
| 330 | MyFrameHandler myFrameHandler; |
| 331 | |
| 332 | MyFrame::MyFrame() |
| 333 | { |
| 334 | Bind( wxEVT_COMMAND_MENU_SELECTED, &MyFrameHandler::OnFrameExit, |
| 335 | &myFrameHandler, wxID_EXIT ); |
| 336 | } |
| 337 | @endcode |
| 338 | |
| 339 | Note that @c MyFrameHandler doesn't need to derive from wxEvtHandler. But |
| 340 | keep in mind that then the lifetime of @c myFrameHandler must be greater than |
| 341 | that of @c MyFrame object -- or at least it needs to be unbound before being |
| 342 | destroyed. |
| 343 | |
| 344 | |
| 345 | To use an ordinary function or a static method as an event handler you would |
| 346 | write something like this: |
| 347 | |
| 348 | @code |
| 349 | void HandleExit( wxCommandEvent & ) |
| 350 | { |
| 351 | // Do something useful |
| 352 | } |
| 353 | |
| 354 | MyFrame::MyFrame() |
| 355 | { |
| 356 | Bind( wxEVT_COMMAND_MENU_SELECTED, &HandleExit, wxID_EXIT ); |
| 357 | } |
| 358 | @endcode |
| 359 | |
| 360 | And finally you can bind to an arbitrary functor and use it as an event |
| 361 | handler: |
| 362 | |
| 363 | @code |
| 364 | |
| 365 | struct MyFunctor |
| 366 | { |
| 367 | void operator()( wxCommandEvent & ) |
| 368 | { |
| 369 | // Do something useful |
| 370 | } |
| 371 | }; |
| 372 | |
| 373 | MyFunctor myFunctor; |
| 374 | |
| 375 | MyFrame::MyFrame() |
| 376 | { |
| 377 | Bind( wxEVT_COMMAND_MENU_SELECTED, myFunctor, wxID_EXIT ); |
| 378 | } |
| 379 | @endcode |
| 380 | |
| 381 | A common example of a functor is boost::function<>: |
| 382 | |
| 383 | @code |
| 384 | using namespace boost; |
| 385 | |
| 386 | void MyHandler::OnExit( wxCommandEvent & ) |
| 387 | { |
| 388 | // Do something useful |
| 389 | } |
| 390 | |
| 391 | MyHandler myHandler; |
| 392 | |
| 393 | MyFrame::MyFrame() |
| 394 | { |
| 395 | function< void ( wxCommandEvent & ) > exitHandler( bind( &MyHandler::OnExit, &myHandler, _1 )); |
| 396 | |
| 397 | Bind( wxEVT_COMMAND_MENU_SELECTED, exitHandler, wxID_EXIT ); |
| 398 | } |
| 399 | @endcode |
| 400 | |
| 401 | |
| 402 | With the aid of boost::bind<>() you can even use methods or functions which |
| 403 | don't quite have the correct signature: |
| 404 | |
| 405 | @code |
| 406 | void MyHandler::OnExit( int exitCode, wxCommandEvent &, wxString goodByeMessage ) |
| 407 | { |
| 408 | // Do something useful |
| 409 | } |
| 410 | |
| 411 | MyHandler myHandler; |
| 412 | |
| 413 | MyFrame::MyFrame() |
| 414 | { |
| 415 | function< void ( wxCommandEvent & ) > exitHandler( |
| 416 | bind( &MyHandler::OnExit, &myHandler, EXIT_FAILURE, _1, "Bye" )); |
| 417 | |
| 418 | Bind( wxEVT_COMMAND_MENU_SELECTED, exitHandler, wxID_EXIT ); |
| 419 | } |
| 420 | @endcode |
| 421 | |
| 422 | |
| 423 | To summarize, using Bind<>() requires slightly more typing but is much more |
| 424 | flexible than using static event tables so don't hesitate to use it when you |
| 425 | need this extra power. On the other hand, event tables are still perfectly fine |
| 426 | in simple situations where this extra flexibility is not needed. |
| 427 | |
| 428 | |
| 429 | @section overview_events_processing How Events are Processed |
| 430 | |
| 431 | The previous sections explain how to define event handlers but don't address |
| 432 | the question of how exactly wxWidgets finds the handler to call for the |
| 433 | given event. This section describes the algorithm used in detail. Notice that |
| 434 | you may want to run the @ref page_samples_event while reading this section and |
| 435 | look at its code and the output when the button which can be used to test the |
| 436 | event handlers execution order is clicked to understand it better. |
| 437 | |
| 438 | When an event is received from the windowing system, wxWidgets calls |
| 439 | wxEvtHandler::ProcessEvent() on the first event handler object belonging to the |
| 440 | window generating the event. The normal order of event table searching by |
| 441 | ProcessEvent() is as follows, with the event processing stopping as soon as a |
| 442 | handler is found (unless the handler calls wxEvent::Skip() in which case it |
| 443 | doesn't count as having handled the event and the search continues): |
| 444 | <ol> |
| 445 | <li value="0"> |
| 446 | Before anything else happens, wxApp::FilterEvent() is called. If it returns |
| 447 | anything but -1 (default), the event handling stops immediately. |
| 448 | </li> |
| 449 | |
| 450 | <li value="1"> |
| 451 | If this event handler is disabled via a call to |
| 452 | wxEvtHandler::SetEvtHandlerEnabled() the next three steps are skipped and |
| 453 | the event handler resumes at step (5). |
| 454 | </li> |
| 455 | |
| 456 | <li value="2"> |
| 457 | If the object is a wxWindow and has an associated validator, wxValidator |
| 458 | gets a chance to process the event. |
| 459 | </li> |
| 460 | |
| 461 | <li value="3"> |
| 462 | The list of dynamically bound event handlers, i.e., those for which |
| 463 | Bind<>() was called, is consulted. Notice that this is done before |
| 464 | checking the static event table entries, so if both a dynamic and a static |
| 465 | event handler match the same event, the static one is never going to be |
| 466 | used unless wxEvent::Skip() is called in the dynamic one. |
| 467 | </li> |
| 468 | |
| 469 | <li value="4"> |
| 470 | The event table containing all the handlers defined using the event table |
| 471 | macros in this class and its base classes is examined. Notice that this |
| 472 | means that any event handler defined in a base class will be executed at |
| 473 | this step. |
| 474 | </li> |
| 475 | |
| 476 | <li value="5"> |
| 477 | The event is passed to the next event handler, if any, in the event handler |
| 478 | chain, i.e., the steps (1) to (4) are done for it. Usually there is no next |
| 479 | event handler so the control passes to the next step but see @ref |
| 480 | overview_events_nexthandler for how the next handler may be defined. |
| 481 | </li> |
| 482 | |
| 483 | <li value="6"> |
| 484 | If the object is a wxWindow and the event is set to propagate (by default |
| 485 | only wxCommandEvent-derived events are set to propagate), then the |
| 486 | processing restarts from the step (1) (and excluding the step (7)) for the |
| 487 | parent window. If this object is not a window but the next handler exists, |
| 488 | the event is passed to its parent if it is a window. This ensures that in a |
| 489 | common case of (possibly several) non-window event handlers pushed on top |
| 490 | of a window, the event eventually reaches the window parent. |
| 491 | </li> |
| 492 | |
| 493 | <li value="7"> |
| 494 | Finally, i.e., if the event is still not processed, the wxApp object itself |
| 495 | (which derives from wxEvtHandler) gets a last chance to process it. |
| 496 | </li> |
| 497 | </ol> |
| 498 | |
| 499 | <em>Please pay close attention to step 6!</em> People often overlook or get |
| 500 | confused by this powerful feature of the wxWidgets event processing system. The |
| 501 | details of event propagation up the window hierarchy are described in the |
| 502 | next section. |
| 503 | |
| 504 | Also please notice that there are additional steps in the event handling for |
| 505 | the windows-making part of wxWidgets document-view framework, i.e., |
| 506 | wxDocParentFrame, wxDocChildFrame and their MDI equivalents wxDocMDIParentFrame |
| 507 | and wxDocMDIChildFrame. The parent frame classes modify step (2) above to |
| 508 | send the events received by them to wxDocManager object first. This object, in |
| 509 | turn, sends the event to the current view and the view itself lets its |
| 510 | associated document process the event first. The child frame classes send |
| 511 | the event directly to the associated view which still forwards it to its |
| 512 | document object. Notice that to avoid remembering the exact order in which the |
| 513 | events are processed in the document-view frame, the simplest, and recommended, |
| 514 | solution is to only handle the events at the view classes level, and not in the |
| 515 | document or document manager classes |
| 516 | |
| 517 | |
| 518 | @subsection overview_events_propagation How Events Propagate Upwards |
| 519 | |
| 520 | As mentioned above, the events of the classes deriving from wxCommandEvent are |
| 521 | propagated by default to the parent window if they are not processed in this |
| 522 | window itself. But although by default only the command events are propagated |
| 523 | like this, other events can be propagated as well because the event handling |
| 524 | code uses wxEvent::ShouldPropagate() to check whether an event should be |
| 525 | propagated. It is also possible to propagate the event only a limited number of |
| 526 | times and not until it is processed (or a top level parent window is reached). |
| 527 | |
| 528 | Finally, there is another additional complication (which, in fact, simplifies |
| 529 | life of wxWidgets programmers significantly): when propagating the command |
| 530 | events up to the parent window, the event propagation stops when it |
| 531 | reaches the parent dialog, if any. This means that you don't risk getting |
| 532 | unexpected events from the dialog controls (which might be left unprocessed by |
| 533 | the dialog itself because it doesn't care about them) when a modal dialog is |
| 534 | popped up. The events do propagate beyond the frames, however. The rationale |
| 535 | for this choice is that there are only a few frames in a typical application |
| 536 | and their parent-child relation are well understood by the programmer while it |
| 537 | may be difficult, if not impossible, to track down all the dialogs that |
| 538 | may be popped up in a complex program (remember that some are created |
| 539 | automatically by wxWidgets). If you need to specify a different behaviour for |
| 540 | some reason, you can use <tt>wxWindow::SetExtraStyle(wxWS_EX_BLOCK_EVENTS)</tt> |
| 541 | explicitly to prevent the events from being propagated beyond the given window |
| 542 | or unset this flag for the dialogs that have it on by default. |
| 543 | |
| 544 | Typically events that deal with a window as a window (size, motion, |
| 545 | paint, mouse, keyboard, etc.) are sent only to the window. Events |
| 546 | that have a higher level of meaning or are generated by the window |
| 547 | itself (button click, menu select, tree expand, etc.) are command |
| 548 | events and are sent up to the parent to see if it is interested in the event. |
| 549 | More precisely, as said above, all event classes @b not deriving from wxCommandEvent |
| 550 | (see the wxEvent inheritance map) do @b not propagate upward. |
| 551 | |
| 552 | In some cases, it might be desired by the programmer to get a certain number |
| 553 | of system events in a parent window, for example all key events sent to, but not |
| 554 | used by, the native controls in a dialog. In this case, a special event handler |
| 555 | will have to be written that will override ProcessEvent() in order to pass |
| 556 | all events (or any selection of them) to the parent window. |
| 557 | |
| 558 | |
| 559 | @subsection overview_events_nexthandler Event Handlers Chain |
| 560 | |
| 561 | The step 4 of the event propagation algorithm checks for the next handler in |
| 562 | the event handler chain. This chain can be formed using |
| 563 | wxEvtHandler::SetNextHandler(): |
| 564 | @image html overview_events_chain.png |
| 565 | (referring to the image, if @c A->ProcessEvent is called and it doesn't handle |
| 566 | the event, @c B->ProcessEvent will be called and so on...). |
| 567 | |
| 568 | Additionally, in the case of wxWindow you can build a stack (implemented using |
| 569 | wxEvtHandler double-linked list) using wxWindow::PushEventHandler(): |
| 570 | @image html overview_events_winstack.png |
| 571 | (referring to the image, if @c W->ProcessEvent is called, it immediately calls |
| 572 | @c A->ProcessEvent; if nor @c A nor @c B handle the event, then the wxWindow |
| 573 | itself is used -- i.e. the dynamically bind event handlers and static event |
| 574 | table entries of wxWindow are looked as the last possibility, after all pushed |
| 575 | event handlers were tested). |
| 576 | |
| 577 | By default the chain is empty, i.e. there is no next handler. |
| 578 | |
| 579 | |
| 580 | @section overview_events_custom Custom Event Summary |
| 581 | |
| 582 | @subsection overview_events_custom_general General approach |
| 583 | |
| 584 | As each event is uniquely defined by its event type, defining a custom event |
| 585 | starts with defining a new event type for it. This is done using |
| 586 | wxDEFINE_EVENT() macro. As an event type is a variable, it can also be |
| 587 | declared using wxDECLARE_EVENT() if necessary. |
| 588 | |
| 589 | The next thing to do is to decide whether you need to define a custom event |
| 590 | class for events of this type or if you can reuse an existing class, typically |
| 591 | either wxEvent (which doesn't provide any extra information) or wxCommandEvent |
| 592 | (which contains several extra fields and also propagates upwards by default). |
| 593 | Both strategies are described in details below. See also the @ref |
| 594 | page_samples_event for a complete example of code defining and working with the |
| 595 | custom event types. |
| 596 | |
| 597 | Finally, you will need to generate and post your custom events. |
| 598 | Generation is as simple as instancing your custom event class and initializing |
| 599 | its internal fields. |
| 600 | For posting events to a certain event handler there are two possibilities: |
| 601 | using wxEvtHandler::AddPendingEvent or using wxEvtHandler::QueueEvent. |
| 602 | Basically you will need to use the latter when doing inter-thread communication; |
| 603 | when you use only the main thread you can also safely use the former. |
| 604 | Last, note that there are also two simple global wrapper functions associated |
| 605 | to the two wxEvtHandler mentioned functions: wxPostEvent() and wxQueueEvent(). |
| 606 | |
| 607 | |
| 608 | @subsection overview_events_custom_existing Using Existing Event Classes |
| 609 | |
| 610 | If you just want to use a wxCommandEvent with a new event type, use one of the |
| 611 | generic event table macros listed below, without having to define a new event |
| 612 | class yourself. |
| 613 | |
| 614 | Example: |
| 615 | |
| 616 | @code |
| 617 | // this is typically in a header: it just declares MY_EVENT event type |
| 618 | wxDECLARE_EVENT(MY_EVENT, wxCommandEvent); |
| 619 | |
| 620 | // this is a definition so can't be in a header |
| 621 | wxDEFINE_EVENT(MY_EVENT, wxCommandEvent); |
| 622 | |
| 623 | // example of code handling the event with event tables |
| 624 | wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) |
| 625 | EVT_MENU (wxID_EXIT, MyFrame::OnExit) |
| 626 | ... |
| 627 | EVT_COMMAND (ID_MY_WINDOW, MY_EVENT, MyFrame::OnMyEvent) |
| 628 | wxEND_EVENT_TABLE() |
| 629 | |
| 630 | void MyFrame::OnMyEvent(wxCommandEvent& event) |
| 631 | { |
| 632 | // do something |
| 633 | wxString text = event.GetString(); |
| 634 | } |
| 635 | |
| 636 | // example of code handling the event with Bind<>(): |
| 637 | MyFrame::MyFrame() |
| 638 | { |
| 639 | Bind(MY_EVENT, &MyFrame::OnMyEvent, this, ID_MY_WINDOW); |
| 640 | } |
| 641 | |
| 642 | // example of code generating the event |
| 643 | void MyWindow::SendEvent() |
| 644 | { |
| 645 | wxCommandEvent event(MY_EVENT, GetId()); |
| 646 | event.SetEventObject(this); |
| 647 | |
| 648 | // Give it some contents |
| 649 | event.SetString("Hello"); |
| 650 | |
| 651 | // Do send it |
| 652 | ProcessWindowEvent(event); |
| 653 | } |
| 654 | @endcode |
| 655 | |
| 656 | |
| 657 | @subsection overview_events_custom_ownclass Defining Your Own Event Class |
| 658 | |
| 659 | Under certain circumstances, you must define your own event class e.g., for |
| 660 | sending more complex data from one place to another. Apart from defining your |
| 661 | event class, you also need to define your own event table macro if you want to |
| 662 | use event tables for handling events of this type. |
| 663 | |
| 664 | Here is an example: |
| 665 | |
| 666 | @code |
| 667 | // define a new event class |
| 668 | class MyPlotEvent: public wxEvent |
| 669 | { |
| 670 | public: |
| 671 | MyPlotEvent(wxEventType eventType, int winid, const wxPoint& pos) |
| 672 | : wxEvent(winid, eventType), |
| 673 | m_pos(pos) |
| 674 | { |
| 675 | } |
| 676 | |
| 677 | // accessors |
| 678 | wxPoint GetPoint() const { return m_pos; } |
| 679 | |
| 680 | // implement the base class pure virtual |
| 681 | virtual wxEvent *Clone() const { return new MyPlotEvent(*this); } |
| 682 | |
| 683 | private: |
| 684 | const wxPoint m_pos; |
| 685 | }; |
| 686 | |
| 687 | // we define a single MY_PLOT_CLICKED event type associated with the class |
| 688 | // above but typically you are going to have more than one event type, e.g. you |
| 689 | // could also have MY_PLOT_ZOOMED or MY_PLOT_PANNED &c -- in which case you |
| 690 | // would just add more similar lines here |
| 691 | wxDEFINE_EVENT(MY_PLOT_CLICKED, MyPlotEvent); |
| 692 | |
| 693 | |
| 694 | // if you want to support old compilers you need to use some ugly macros: |
| 695 | typedef void (wxEvtHandler::*MyPlotEventFunction)(MyPlotEvent&); |
| 696 | #define MyPlotEventHandler(func) wxEVENT_HANDLER_CAST(MyPlotEventFunction, func) |
| 697 | |
| 698 | // if your code is only built using reasonably modern compilers, you could just |
| 699 | // do this instead: |
| 700 | #define MyPlotEventHandler(func) (&func) |
| 701 | |
| 702 | // finally define a macro for creating the event table entries for the new |
| 703 | // event type |
| 704 | // |
| 705 | // remember that you don't need this at all if you only use Bind<>() and that |
| 706 | // you can replace MyPlotEventHandler(func) with just &func unless you use a |
| 707 | // really old compiler |
| 708 | #define MY_EVT_PLOT_CLICK(id, func) \ |
| 709 | wx__DECLARE_EVT1(MY_PLOT_CLICKED, id, MyPlotEventHandler(func)) |
| 710 | |
| 711 | |
| 712 | // example of code handling the event (you will use one of these methods, not |
| 713 | // both, of course): |
| 714 | wxBEGIN_EVENT_TABLE(MyFrame, wxFrame) |
| 715 | EVT_PLOT(ID_MY_WINDOW, MyFrame::OnPlot) |
| 716 | wxEND_EVENT_TABLE() |
| 717 | |
| 718 | MyFrame::MyFrame() |
| 719 | { |
| 720 | Bind(MY_PLOT_CLICKED, &MyFrame::OnPlot, this, ID_MY_WINDOW); |
| 721 | } |
| 722 | |
| 723 | void MyFrame::OnPlot(MyPlotEvent& event) |
| 724 | { |
| 725 | ... do something with event.GetPoint() ... |
| 726 | } |
| 727 | |
| 728 | |
| 729 | // example of code generating the event: |
| 730 | void MyWindow::SendEvent() |
| 731 | { |
| 732 | MyPlotEvent event(MY_PLOT_CLICKED, GetId(), wxPoint(...)); |
| 733 | event.SetEventObject(this); |
| 734 | ProcessWindowEvent(event); |
| 735 | } |
| 736 | @endcode |
| 737 | |
| 738 | |
| 739 | |
| 740 | @section overview_events_misc Miscellaneous Notes |
| 741 | |
| 742 | @subsection overview_events_virtual Event Handlers vs Virtual Methods |
| 743 | |
| 744 | It may be noted that wxWidgets' event processing system implements something |
| 745 | close to virtual methods in normal C++ in spirit: both of these mechanisms |
| 746 | allow you to alter the behaviour of the base class by defining the event handling |
| 747 | functions in the derived classes. |
| 748 | |
| 749 | There is however an important difference between the two mechanisms when you |
| 750 | want to invoke the default behaviour, as implemented by the base class, from a |
| 751 | derived class handler. With the virtual functions, you need to call the base |
| 752 | class function directly and you can do it either in the beginning of the |
| 753 | derived class handler function (to post-process the event) or at its end (to |
| 754 | pre-process the event). With the event handlers, you only have the option of |
| 755 | pre-processing the events and in order to still let the default behaviour |
| 756 | happen you must call wxEvent::Skip() and @em not call the base class event |
| 757 | handler directly. In fact, the event handler probably doesn't even exist in the |
| 758 | base class as the default behaviour is often implemented in platform-specific |
| 759 | code by the underlying toolkit or OS itself. But even if it does exist at |
| 760 | wxWidgets level, it should never be called directly as the event handlers are |
| 761 | not part of wxWidgets API and should never be called directly. |
| 762 | |
| 763 | |
| 764 | |
| 765 | @subsection overview_events_prog User Generated Events vs Programmatically Generated Events |
| 766 | |
| 767 | While generically wxEvents can be generated both by user |
| 768 | actions (e.g., resize of a wxWindow) and by calls to functions |
| 769 | (e.g., wxWindow::SetSize), wxWidgets controls normally send wxCommandEvent-derived |
| 770 | events only for the user-generated events. The only @b exceptions to this rule are: |
| 771 | |
| 772 | @li wxNotebook::AddPage: No event-free alternatives |
| 773 | @li wxNotebook::AdvanceSelection: No event-free alternatives |
| 774 | @li wxNotebook::DeletePage: No event-free alternatives |
| 775 | @li wxNotebook::SetSelection: Use wxNotebook::ChangeSelection instead, as |
| 776 | wxNotebook::SetSelection is deprecated |
| 777 | @li wxTreeCtrl::Delete: No event-free alternatives |
| 778 | @li wxTreeCtrl::DeleteAllItems: No event-free alternatives |
| 779 | @li wxTreeCtrl::EditLabel: No event-free alternatives |
| 780 | @li All wxTextCtrl methods |
| 781 | |
| 782 | wxTextCtrl::ChangeValue can be used instead of wxTextCtrl::SetValue but the other |
| 783 | functions, such as wxTextCtrl::Replace or wxTextCtrl::WriteText don't have event-free |
| 784 | equivalents. |
| 785 | |
| 786 | |
| 787 | |
| 788 | @subsection overview_events_pluggable Pluggable Event Handlers |
| 789 | |
| 790 | <em>TODO: Probably deprecated, Bind() provides a better way to do this</em> |
| 791 | |
| 792 | In fact, you don't have to derive a new class from a window class |
| 793 | if you don't want to. You can derive a new class from wxEvtHandler instead, |
| 794 | defining the appropriate event table, and then call wxWindow::SetEventHandler |
| 795 | (or, preferably, wxWindow::PushEventHandler) to make this |
| 796 | event handler the object that responds to events. This way, you can avoid |
| 797 | a lot of class derivation, and use instances of the same event handler class (but different |
| 798 | objects as the same event handler object shouldn't be used more than once) to |
| 799 | handle events from instances of different widget classes. |
| 800 | |
| 801 | If you ever have to call a window's event handler |
| 802 | manually, use the GetEventHandler function to retrieve the window's event handler and use that |
| 803 | to call the member function. By default, GetEventHandler returns a pointer to the window itself |
| 804 | unless an application has redirected event handling using SetEventHandler or PushEventHandler. |
| 805 | |
| 806 | One use of PushEventHandler is to temporarily or permanently change the |
| 807 | behaviour of the GUI. For example, you might want to invoke a dialog editor |
| 808 | in your application that changes aspects of dialog boxes. You can |
| 809 | grab all the input for an existing dialog box, and edit it 'in situ', |
| 810 | before restoring its behaviour to normal. So even if the application |
| 811 | has derived new classes to customize behaviour, your utility can indulge |
| 812 | in a spot of body-snatching. It could be a useful technique for on-line |
| 813 | tutorials, too, where you take a user through a serious of steps and |
| 814 | don't want them to diverge from the lesson. Here, you can examine the events |
| 815 | coming from buttons and windows, and if acceptable, pass them through to |
| 816 | the original event handler. Use PushEventHandler/PopEventHandler |
| 817 | to form a chain of event handlers, where each handler processes a different |
| 818 | range of events independently from the other handlers. |
| 819 | |
| 820 | |
| 821 | |
| 822 | @subsection overview_events_winid Window Identifiers |
| 823 | |
| 824 | Window identifiers are integers, and are used to |
| 825 | uniquely determine window identity in the event system (though you can use it |
| 826 | for other purposes). In fact, identifiers do not need to be unique |
| 827 | across your entire application as long they are unique within the |
| 828 | particular context you're interested in, such as a frame and its children. You |
| 829 | may use the @c wxID_OK identifier, for example, on any number of dialogs |
| 830 | as long as you don't have several within the same dialog. |
| 831 | |
| 832 | If you pass @c wxID_ANY to a window constructor, an identifier will be |
| 833 | generated for you automatically by wxWidgets. This is useful when you don't |
| 834 | care about the exact identifier either because you're not going to process the |
| 835 | events from the control being created or because you process the events |
| 836 | from all controls in one place (in which case you should specify @c wxID_ANY |
| 837 | in the event table or wxEvtHandler::Bind call |
| 838 | as well). The automatically generated identifiers are always negative and so |
| 839 | will never conflict with the user-specified identifiers which must be always |
| 840 | positive. |
| 841 | |
| 842 | See @ref page_stdevtid for the list of standard identifiers available. |
| 843 | You can use wxID_HIGHEST to determine the number above which it is safe to |
| 844 | define your own identifiers. Or, you can use identifiers below wxID_LOWEST. |
| 845 | Finally, you can allocate identifiers dynamically using wxNewId() function too. |
| 846 | If you use wxNewId() consistently in your application, you can be sure that |
| 847 | your identifiers don't conflict accidentally. |
| 848 | |
| 849 | |
| 850 | @subsection overview_events_custom_generic Generic Event Table Macros |
| 851 | |
| 852 | @beginTable |
| 853 | @row2col{EVT_CUSTOM(event\, id\, func), |
| 854 | Allows you to add a custom event table |
| 855 | entry by specifying the event identifier (such as wxEVT_SIZE), |
| 856 | the window identifier, and a member function to call.} |
| 857 | @row2col{EVT_CUSTOM_RANGE(event\, id1\, id2\, func), |
| 858 | The same as EVT_CUSTOM, but responds to a range of window identifiers.} |
| 859 | @row2col{EVT_COMMAND(id\, event\, func), |
| 860 | The same as EVT_CUSTOM, but expects a member function with a |
| 861 | wxCommandEvent argument.} |
| 862 | @row2col{EVT_COMMAND_RANGE(id1\, id2\, event\, func), |
| 863 | The same as EVT_CUSTOM_RANGE, but |
| 864 | expects a member function with a wxCommandEvent argument.} |
| 865 | @row2col{EVT_NOTIFY(event\, id\, func), |
| 866 | The same as EVT_CUSTOM, but |
| 867 | expects a member function with a wxNotifyEvent argument.} |
| 868 | @row2col{EVT_NOTIFY_RANGE(event\, id1\, id2\, func), |
| 869 | The same as EVT_CUSTOM_RANGE, but |
| 870 | expects a member function with a wxNotifyEvent argument.} |
| 871 | @endTable |
| 872 | |
| 873 | |
| 874 | |
| 875 | @subsection overview_events_list List of wxWidgets events |
| 876 | |
| 877 | For the full list of event classes, please see the |
| 878 | @ref group_class_events "event classes group page". |
| 879 | |
| 880 | |
| 881 | */ |
| 882 | |