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