keep the list of event classes in a single place
[wxWidgets.git] / docs / doxygen / overviews / eventhandling.h
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: eventhandling.h
3 // Purpose: topic overview
4 // Author: wxWidgets team
5 // RCS-ID: $Id$
6 // Licence: wxWindows license
7 /////////////////////////////////////////////////////////////////////////////
8
9 /*!
10
11 @page overview_eventhandling Event handling overview
12
13 Classes: wxEvtHandler, wxWindow, wxEvent
14
15 @li @ref overview_eventhandling_introduction
16 @li @ref overview_eventhandling_processing
17 @li @ref overview_eventhandling_prog
18 @li @ref overview_eventhandling_pluggable
19 @li @ref overview_eventhandling_winid
20 @li @ref overview_eventhandling_custom
21 @li @ref overview_eventhandling_macros
22
23
24 <hr>
25
26
27 @section overview_eventhandling_introduction Introduction
28
29 Before version 2.0 of wxWidgets, events were handled by the application
30 either by supplying callback functions, or by overriding virtual member
31 functions such as @b OnSize.
32
33 From wxWidgets 2.0, @e event tables are used instead, with a few exceptions.
34 An event table is placed in an implementation file to tell wxWidgets how to map
35 events to member functions. These member functions are not virtual functions, but
36 they are all similar in form: they take a single wxEvent-derived argument,
37 and have a void return type.
38 Here's an example of an event table.
39
40 @code
41 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
42 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
43 EVT_MENU(DO_TEST, MyFrame::DoTest)
44 EVT_SIZE(MyFrame::OnSize)
45 EVT_BUTTON(BUTTON1, MyFrame::OnButton1)
46 END_EVENT_TABLE()
47 @endcode
48
49 The first two entries map menu commands to two different member functions. The
50 EVT_SIZE macro doesn't need a window identifier, since normally you are only
51 interested in the current window's size events.
52
53 The EVT_BUTTON macro demonstrates that the originating event does not have to
54 come from the window class implementing the event table -- if the event source
55 is a button within a panel within a frame, this will still work, because event
56 tables are searched up through the hierarchy of windows for the command events.
57 In this case, the button's event table will be searched, then the parent
58 panel's, then the frame's.
59
60 As mentioned before, the member functions that handle events do not have to be
61 virtual. Indeed, the member functions should not be virtual as the event
62 handler ignores that the functions are virtual, i.e. overriding a virtual
63 member function in a derived class will not have any effect. These member
64 functions take an event argument, and the class of event differs according to
65 the type of event and the class of the originating window. For size events,
66 wxSizeEvent is used. For menu commands and most control commands
67 (such as button presses), wxCommandEvent is used. When controls get more
68 complicated, then specific event classes are used, such as wxTreeEvent for
69 events from wxTreeCtrl windows.
70
71 As well as the event table in the implementation file, there must also be a
72 DECLARE_EVENT_TABLE macro somewhere in the class declaration. For example:
73
74 @code
75 class MyFrame : public wxFrame
76 {
77 public:
78 ...
79 void OnExit(wxCommandEvent& event);
80 void OnSize(wxSizeEvent& event);
81
82 protected:
83 int m_count;
84 ...
85
86 DECLARE_EVENT_TABLE()
87 };
88 @endcode
89
90 Note that this macro may occur in any section of the class (public, protected
91 or private) but that it is probably better to insert it at the end, as shown,
92 because this macro implicitly changes the access to protected which may be
93 quite unexpected if there is anything following it.
94
95 Finally, if you don't like using macros for static initialization of the event
96 tables you may also use wxEvtHandler::Connect to
97 connect the events to the handlers dynamically, during run-time. See the
98 @ref page_utils_samples_event for an example of doing it.
99
100
101
102 @section overview_eventhandling_processing How events are processed
103
104 When an event is received from the windowing system, wxWidgets calls
105 wxEvtHandler::ProcessEvent on the first
106 event handler object belonging to the window generating the event.
107
108 It may be noted that wxWidgets' event processing system implements something
109 very close to virtual methods in normal C++, i.e. it is possible to alter
110 the behaviour of a class by overriding its event handling functions. In
111 many cases this works even for changing the behaviour of native controls.
112
113 For example it is possible to filter out a number of key events sent by the
114 system to a native text control by overriding wxTextCtrl and defining a
115 handler for key events using EVT_KEY_DOWN. This would indeed prevent
116 any key events from being sent to the native control - which might not be
117 what is desired. In this case the event handler function has to call Skip()
118 so as to indicate that the search for the event handler should continue.
119
120 To summarize, instead of explicitly calling the base class version as you
121 would have done with C++ virtual functions (i.e. @e wxTextCtrl::OnChar()),
122 you should instead call wxEvent::Skip.
123
124 In practice, this would look like this if the derived text control only
125 accepts 'a' to 'z' and 'A' to 'Z':
126
127 @code
128 void MyTextCtrl::OnChar(wxKeyEvent& event)
129 {
130 if ( isalpha( event.KeyCode() ) )
131 {
132 // key code is within legal range. we call event.Skip() so the
133 // event can be processed either in the base wxWidgets class
134 // or the native control.
135
136 event.Skip();
137 }
138 else
139 {
140 // illegal key hit. we don't call event.Skip() so the
141 // event is not processed anywhere else.
142
143 wxBell();
144 }
145 }
146 @endcode
147
148 The normal order of event table searching by ProcessEvent is as follows:
149
150 @li If the object is disabled (via a call to wxEvtHandler::SetEvtHandlerEnabled)
151 the function skips to step (6).
152 @li If the object is a wxWindow, @b ProcessEvent is recursively called on the window's
153 wxValidator. If this returns @true, the function exits.
154 @li @b SearchEventTable is called for this event handler. If this fails, the base
155 class table is tried, and so on until no more tables exist or an appropriate
156 function was found, in which case the function exits.
157 @li The search is applied down the entire chain of event handlers (usually the chain has
158 a length of one). If this succeeds, the function exits.
159 @li If the object is a wxWindow and the event is set to set to propagate (in the library only
160 wxCommandEvent based events are set to propagate), @b ProcessEvent is recursively applied
161 to the parent window's event handler. If this returns @true, the function exits.
162 @li Finally, @b ProcessEvent is called on the wxApp object.
163
164 <b>Pay close attention to Step 5</b>. People often overlook or get
165 confused by this powerful feature of the wxWidgets event processing
166 system. To put it a different way, events set to propagate
167 (see wxEvent::ShouldPropagate)
168 (most likely derived either directly or indirectly from wxCommandEvent)
169 will travel up the containment hierarchy from child to parent until the
170 maximal propagation level is reached or an event handler is found that
171 doesn't call @c event.Skip().
172
173 Finally, there is another additional complication (which, in fact, simplifies
174 life of wxWidgets programmers significantly): when propagating the command
175 events upwards to the parent window, the event propagation stops when it
176 reaches the parent dialog, if any. This means that you don't risk to get
177 unexpected events from the dialog controls (which might be left unprocessed by
178 the dialog itself because it doesn't care about them) when a modal dialog is
179 popped up. The events do propagate beyond the frames, however. The rationale
180 for this choice is that there are only a few frames in a typical application
181 and their parent-child relation are well understood by the programmer while it
182 may be very difficult, if not impossible, to track down all the dialogs which
183 may be popped up in a complex program (remember that some are created
184 automatically by wxWidgets). If you need to specify a different behaviour for
185 some reason, you can use wxWindow::SetExtraStyle(wxWS_EX_BLOCK_EVENTS)
186 explicitly to prevent the events from being propagated beyond the given window
187 or unset this flag for the dialogs which have it on by default.
188
189 Typically events that deal with a window as a window (size, motion,
190 paint, mouse, keyboard, etc.) are sent only to the window. Events
191 that have a higher level of meaning and/or are generated by the window
192 itself, (button click, menu select, tree expand, etc.) are command
193 events and are sent up to the parent to see if it is interested in the event.
194
195 Note that your application may wish to override ProcessEvent to redirect processing of
196 events. This is done in the document/view framework, for example, to allow event handlers
197 to be defined in the document or view. To test for command events (which will probably
198 be the only events you wish to redirect), you may use wxEvent::IsCommandEvent for efficiency,
199 instead of using the slower run-time type system.
200
201 As mentioned above, only command events are recursively applied to the parents event
202 handler in the library itself. As this quite often causes confusion for users,
203 here is a list of system events which will NOT get sent to the parent's event handler:
204
205 @li wxEvent: The event base class
206 @li wxActivateEvent: A window or application activation event
207 @li wxCloseEvent: A close window or end session event
208 @li wxEraseEvent: An erase background event
209 @li wxFocusEvent: A window focus event
210 @li wxKeyEvent: A keypress event
211 @li wxIdleEvent: An idle event
212 @li wxInitDialogEvent: A dialog initialisation event
213 @li wxJoystickEvent: A joystick event
214 @li wxMenuEvent: A menu event
215 @li wxMouseEvent: A mouse event
216 @li wxMoveEvent: A move event
217 @li wxPaintEvent: A paint event
218 @li wxQueryLayoutInfoEvent: Used to query layout information
219 @li wxSetCursorEvent: Used for special cursor processing based on current mouse position
220 @li wxSizeEvent: A size event
221 @li wxScrollWinEvent: A scroll event sent by a scrolled window (not a scroll bar)
222 @li wxSysColourChangedEvent: A system colour change event
223
224 In some cases, it might be desired by the programmer to get a certain number
225 of system events in a parent window, for example all key events sent to, but not
226 used by, the native controls in a dialog. In this case, a special event handler
227 will have to be written that will override ProcessEvent() in order to pass
228 all events (or any selection of them) to the parent window.
229
230
231 @section overview_eventhandling_prog Events generated by the user vs programmatically generated events
232
233 While generically wxEvents can be generated both by user
234 actions (e.g. resize of a wxWindow) and by calls to functions
235 (e.g. wxWindow::SetSize), wxWidgets controls normally send wxCommandEvent-derived
236 events only for the user-generated events. The only @b exceptions to this rule are:
237
238 @li wxNotebook::AddPage: No event-free alternatives
239 @li wxNotebook::AdvanceSelection: No event-free alternatives
240 @li wxNotebook::DeletePage: No event-free alternatives
241 @li wxNotebook::SetSelection: Use wxNotebook::ChangeSelection instead, as
242 wxNotebook::SetSelection is deprecated
243 @li wxTreeCtrl::Delete: No event-free alternatives
244 @li wxTreeCtrl::DeleteAllItems: No event-free alternatives
245 @li wxTreeCtrl::EditLabel: No event-free alternatives
246 @li All wxTextCtrl methods
247
248 wxTextCtrl::ChangeValue can be used instead of wxTextCtrl::SetValue but the other
249 functions, such as wxTextCtrl::Replace or wxTextCtrl::WriteText don't have event-free
250 equivalents.
251
252
253
254 @section overview_eventhandling_pluggable Pluggable event handlers
255
256 In fact, you don't have to derive a new class from a window class
257 if you don't want to. You can derive a new class from wxEvtHandler instead,
258 defining the appropriate event table, and then call wxWindow::SetEventHandler
259 (or, preferably, wxWindow::PushEventHandler) to make this
260 event handler the object that responds to events. This way, you can avoid
261 a lot of class derivation, and use instances of the same event handler class (but different
262 objects as the same event handler object shouldn't be used more than once) to
263 handle events from instances of different widget classes.
264
265 If you ever have to call a window's event handler
266 manually, use the GetEventHandler function to retrieve the window's event handler and use that
267 to call the member function. By default, GetEventHandler returns a pointer to the window itself
268 unless an application has redirected event handling using SetEventHandler or PushEventHandler.
269
270 One use of PushEventHandler is to temporarily or permanently change the
271 behaviour of the GUI. For example, you might want to invoke a dialog editor
272 in your application that changes aspects of dialog boxes. You can
273 grab all the input for an existing dialog box, and edit it 'in situ',
274 before restoring its behaviour to normal. So even if the application
275 has derived new classes to customize behaviour, your utility can indulge
276 in a spot of body-snatching. It could be a useful technique for on-line
277 tutorials, too, where you take a user through a serious of steps and
278 don't want them to diverge from the lesson. Here, you can examine the events
279 coming from buttons and windows, and if acceptable, pass them through to
280 the original event handler. Use PushEventHandler/PopEventHandler
281 to form a chain of event handlers, where each handler processes a different
282 range of events independently from the other handlers.
283
284
285
286 @section overview_eventhandling_winid Window identifiers
287
288 Window identifiers are integers, and are used to
289 uniquely determine window identity in the event system (though you can use it
290 for other purposes). In fact, identifiers do not need to be unique
291 across your entire application just so long as they are unique within a
292 particular context you're interested in, such as a frame and its children. You
293 may use the @c wxID_OK identifier, for example, on any number of dialogs so
294 long as you don't have several within the same dialog.
295
296 If you pass @c wxID_ANY to a window constructor, an identifier will be
297 generated for you automatically by wxWidgets. This is useful when you don't
298 care about the exact identifier either because you're not going to process the
299 events from the control being created at all or because you process the events
300 from all controls in one place (in which case you should specify @c wxID_ANY
301 in the event table or wxEvtHandler::Connect call
302 as well. The automatically generated identifiers are always negative and so
303 will never conflict with the user-specified identifiers which must be always
304 positive.
305
306 The following standard identifiers are supplied. You can use wxID_HIGHEST to
307 determine the number above which it is safe to define your own identifiers. Or,
308 you can use identifiers below wxID_LOWEST.
309
310 @code
311 #define wxID_ANY -1
312
313 #define wxID_LOWEST 4999
314
315 #define wxID_OPEN 5000
316 #define wxID_CLOSE 5001
317 #define wxID_NEW 5002
318 #define wxID_SAVE 5003
319 #define wxID_SAVEAS 5004
320 #define wxID_REVERT 5005
321 #define wxID_EXIT 5006
322 #define wxID_UNDO 5007
323 #define wxID_REDO 5008
324 #define wxID_HELP 5009
325 #define wxID_PRINT 5010
326 #define wxID_PRINT_SETUP 5011
327 #define wxID_PREVIEW 5012
328 #define wxID_ABOUT 5013
329 #define wxID_HELP_CONTENTS 5014
330 #define wxID_HELP_COMMANDS 5015
331 #define wxID_HELP_PROCEDURES 5016
332 #define wxID_HELP_CONTEXT 5017
333
334 #define wxID_CUT 5030
335 #define wxID_COPY 5031
336 #define wxID_PASTE 5032
337 #define wxID_CLEAR 5033
338 #define wxID_FIND 5034
339 #define wxID_DUPLICATE 5035
340 #define wxID_SELECTALL 5036
341 #define wxID_DELETE 5037
342 #define wxID_REPLACE 5038
343 #define wxID_REPLACE_ALL 5039
344 #define wxID_PROPERTIES 5040
345
346 #define wxID_VIEW_DETAILS 5041
347 #define wxID_VIEW_LARGEICONS 5042
348 #define wxID_VIEW_SMALLICONS 5043
349 #define wxID_VIEW_LIST 5044
350 #define wxID_VIEW_SORTDATE 5045
351 #define wxID_VIEW_SORTNAME 5046
352 #define wxID_VIEW_SORTSIZE 5047
353 #define wxID_VIEW_SORTTYPE 5048
354
355 #define wxID_FILE1 5050
356 #define wxID_FILE2 5051
357 #define wxID_FILE3 5052
358 #define wxID_FILE4 5053
359 #define wxID_FILE5 5054
360 #define wxID_FILE6 5055
361 #define wxID_FILE7 5056
362 #define wxID_FILE8 5057
363 #define wxID_FILE9 5058
364
365 #define wxID_OK 5100
366 #define wxID_CANCEL 5101
367 #define wxID_APPLY 5102
368 #define wxID_YES 5103
369 #define wxID_NO 5104
370 #define wxID_STATIC 5105
371
372 #define wxID_HIGHEST 5999
373 @endcode
374
375
376
377 @section overview_eventhandling_custom Custom event summary
378
379 @subsection overview_eventhandling_custom_general General approach
380
381 Since version 2.2.x of wxWidgets, each event type is identified by ID which
382 is given to the event type @e at runtime which makes it possible to add
383 new event types to the library or application without risking ID clashes
384 (two different event types mistakingly getting the same event ID). This
385 event type ID is stored in a struct of type @b const wxEventType.
386
387 In order to define a new event type, there are principally two choices.
388 One is to define a entirely new event class (typically deriving from
389 wxEvent or wxCommandEvent.
390
391 The other is to use the existing event classes and give them an new event
392 type. You'll have to define and declare a new event type using either way,
393 and this is done using the following macros:
394
395 @code
396 // in the header of the source file
397 BEGIN_DECLARE_EVENT_TYPES()
398 DECLARE_EVENT_TYPE(name, value)
399 END_DECLARE_EVENT_TYPES()
400
401 // in the implementation
402 DEFINE_EVENT_TYPE(name)
403 @endcode
404
405 You can ignore the @e value parameter of the DECLARE_EVENT_TYPE macro
406 since it is used only for backwards compatibility with wxWidgets 2.0.x based
407 applications where you have to give the event type ID an explicit value.
408 See also the @ref page_utils_samples_event for an example of code
409 defining and working with the custom event types.
410
411
412 @subsection overview_eventhandling_custom_existing Using existing event classes
413
414 If you just want to use a wxCommandEvent with
415 a new event type, you can then use one of the generic event table macros
416 listed below, without having to define a new macro yourself. This also
417 has the advantage that you won't have to define a new wxEvent::Clone()
418 method for posting events between threads etc. This could look like this
419 in your code:
420
421 @code
422 DECLARE_EVENT_TYPE(wxEVT_MY_EVENT, -1)
423 DEFINE_EVENT_TYPE(wxEVT_MY_EVENT)
424
425 // user code intercepting the event
426
427 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
428 EVT_MENU (wxID_EXIT, MyFrame::OnExit)
429 // ....
430 EVT_COMMAND (ID_MY_WINDOW, wxEVT_MY_EVENT, MyFrame::OnMyEvent)
431 END_EVENT_TABLE()
432
433 void MyFrame::OnMyEvent( wxCommandEvent )
434 {
435 // do something
436 wxString text = event.GetText();
437 }
438
439
440 // user code sending the event
441
442 void MyWindow::SendEvent()
443 {
444 wxCommandEvent event( wxEVT_MY_EVENT, GetId() );
445 event.SetEventObject( this );
446 // Give it some contents
447 event.SetText( wxT("Hallo") );
448 // Send it
449 GetEventHandler()->ProcessEvent( event );
450 }
451 @endcode
452
453
454 @subsection overview_eventhandling_custom_generic Generic event table macros
455
456 @beginTable
457 @row2col{EVT_CUSTOM(event\, id\, func),
458 Allows you to add a custom event table
459 entry by specifying the event identifier (such as wxEVT_SIZE),
460 the window identifier, and a member function to call.}
461 @row2col{EVT_CUSTOM_RANGE(event\, id1\, id2\, func),
462 The same as EVT_CUSTOM, but responds to a range of window identifiers.}
463 @row2col{EVT_COMMAND(id\, event\, func),
464 The same as EVT_CUSTOM, but expects a member function with a
465 wxCommandEvent argument.}
466 @row2col{EVT_COMMAND_RANGE(id1\, id2\, event\, func),
467 The same as EVT_CUSTOM_RANGE, but
468 expects a member function with a wxCommandEvent argument.}
469 @row2col{EVT_NOTIFY(event\, id\, func),
470 The same as EVT_CUSTOM, but
471 expects a member function with a wxNotifyEvent argument.}
472 @row2col{EVT_NOTIFY_RANGE(event\, id1\, id2\, func),
473 The same as EVT_CUSTOM_RANGE, but
474 expects a member function with a wxNotifyEvent argument.}
475 @endTable
476
477
478 @subsection overview_eventhandling_custom_ownclass Defining your own event class
479
480 Under certain circumstances, it will be required to define your own event
481 class e.g. for sending more complex data from one place to another. Apart
482 from defining your event class, you will also need to define your own
483 event table macro (which is quite long). Watch out to put in enough
484 casts to the inherited event function. Here is an example:
485
486 @code
487 // code defining event
488
489 class wxPlotEvent: public wxNotifyEvent
490 {
491 public:
492 wxPlotEvent( wxEventType commandType = wxEVT_NULL, int id = 0 );
493
494 // accessors
495 wxPlotCurve *GetCurve()
496 { return m_curve; }
497
498 // required for sending with wxPostEvent()
499 virtual wxEvent *Clone() const;
500
501 private:
502 wxPlotCurve *m_curve;
503 };
504
505 DECLARE_EVENT_TYPE( wxEVT_PLOT_ACTION, -1 )
506
507 typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&);
508
509 #define EVT_PLOT(id, fn) \
510 DECLARE_EVENT_TABLE_ENTRY( wxEVT_PLOT_ACTION, id, -1, \
511 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) \
512 wxStaticCastEvent( wxPlotEventFunction, &fn ), (wxObject *) NULL ),
513
514
515 // code implementing the event type and the event class
516
517 DEFINE_EVENT_TYPE( wxEVT_PLOT_ACTION )
518
519 wxPlotEvent::wxPlotEvent( ...
520
521
522 // user code intercepting the event
523
524 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
525 EVT_PLOT (ID_MY_WINDOW, MyFrame::OnPlot)
526 END_EVENT_TABLE()
527
528 void MyFrame::OnPlot( wxPlotEvent &event )
529 {
530 wxPlotCurve *curve = event.GetCurve();
531 }
532
533
534 // user code sending the event
535
536 void MyWindow::SendEvent()
537 {
538 wxPlotEvent event( wxEVT_PLOT_ACTION, GetId() );
539 event.SetEventObject( this );
540 event.SetCurve( m_curve );
541 GetEventHandler()->ProcessEvent( event );
542 }
543 @endcode
544
545
546
547
548 @section overview_eventhandling_macros Event macros summary
549
550 For the full list of event classes, please see the
551 @ref page_class_cat_events page.
552
553 */
554