added a section about Connect(), improve/streamline the one about event tables
[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
12
13 Classes: wxEvtHandler, wxWindow, wxEvent
14
15 @li @ref overview_eventhandling_introduction
16 @li @ref overview_eventhandling_eventtables
17 @li @ref overview_eventhandling_connect
18 @li @ref overview_eventhandling_processing
19 @li @ref overview_eventhandling_prog
20 @li @ref overview_eventhandling_pluggable
21 @li @ref overview_eventhandling_winid
22 @li @ref overview_eventhandling_custom
23 @li @ref overview_eventhandling_macros
24
25
26 <hr>
27
28
29 @section overview_eventhandling_introduction Introduction
30
31 There are two principal ways to handle events in wxWidgets. One of them uses
32 <em>event table</em> macros and allows to define the connection between events
33 and their handlers only statically, i.e. during program compilation. The other
34 one uses wxEvtHandler::Connect() call and can be used to connect, and
35 disconnect, the handlers dynamically, i.e. during run-time depending on some
36 conditions. It also allows directly connecting the events of one object to a
37 handler method in another object while the static event tables can only handle
38 events in the object where they are defined so using Connect() is more flexible
39 than using the event tables. On the other hand, event tables are more succinct
40 and centralize all event handlers connection in one place. You can either
41 choose a single approach which you find preferable or freely combine both
42 methods in your program in different classes or even in one and the same class,
43 although this is probably sufficiently confusing to be a bad idea.
44
45 But before you make this choice, let us discuss these two ways in some more
46 details: in the next section we provide a short introduction to handling the
47 events using the event tables, please see @ref overview_eventhandling_connect
48 for the discussion of Connect().
49
50 @section overview_eventhandling_eventtables Event Handling with Event Tables
51
52 To use an <em>event table</em> you must first decide in which class you wish to
53 handle the events. The only requirement imposed by wxWidgets is that this class
54 must derive from wxEvtHandler and so, considering that wxWindow derives from
55 it, any classes representing windows can handle events. Simple events such as
56 menu commands are usually processed at the level of a top-level window
57 containing the menu, so let's suppose that you need to handle some events in @c
58 MyFrame class deriving from wxFrame.
59
60 First thing to do is to define one or more <em>event handlers</em>. They
61 are just simple (non-virtual) methods of the class which take as a parameter a
62 reference to an object of wxEvent-derived class and have no return value (any
63 return information is passed via the argument, which is why it is non-const).
64 You also need to insert a macro
65
66 @code
67 DECLARE_EVENT_TABLE()
68 @endcode
69
70 somewhere in the class declaration. It doesn't matter where does it occur but
71 it's customary to put it at the end of it because the macro changes the access
72 type internally and so it's safest if there is nothing that follows it. So the
73 full class declaration might look like this:
74
75 @code
76 class MyFrame : public wxFrame
77 {
78 public:
79 MyFrame(...) : wxFrame(...) { }
80
81 ...
82
83 protected:
84 int m_whatever;
85
86 private:
87 // notice that as the event handlers normally are not called from outside
88 // the class, they normally be private, in particular they don't need at
89 // all to be public
90 void OnExit(wxCommandEvent& event);
91 void OnButton1(wxCommandEvent& event);
92 void OnSize(wxSizeEvent& event);
93
94 // it's common to call the event handlers OnSomething() but there is no
95 // obligation to it, this one is an event handler too:
96 void DoTest(wxCommandEvent& event);
97
98 DECLARE_EVENT_TABLE()
99 };
100 @endcode
101
102 Next the event table must be defined and, as any definition, it must be placed
103 in an implementation file to tell. The event table tells wxWidgets how to map
104 events to member functions and in our example it could look like this:
105
106 @code
107 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
108 EVT_MENU(wxID_EXIT, MyFrame::OnExit)
109 EVT_MENU(DO_TEST, MyFrame::DoTest)
110 EVT_SIZE(MyFrame::OnSize)
111 EVT_BUTTON(BUTTON1, MyFrame::OnButton1)
112 END_EVENT_TABLE()
113 @endcode
114
115 Notice that you must mention a method you want to use for the event handling in
116 the event table definition, just defining it in MyFrame class is @e not enough.
117
118 Let us now look at the details of this definition: the first line means that we
119 are defining the event table for MyFrame class and that its base class is
120 wxFrame, so events not processed by MyFrame will, by default, be handled to
121 wxFrame. The next four lines define connections of individual events to their
122 handlers: the first two of them map menu commands from the items with the
123 identifiers specified as the first macro parameter to two different member
124 functions. In the next one, @c EVT_SIZE means that any changes in the size of
125 the frame will result in calling OnSize() method. Note that this macro doesn't
126 need a window identifier, since normally you are only interested in the current
127 window's size events.
128
129 The EVT_BUTTON macro demonstrates that the originating event does not have to
130 come from the window class implementing the event table -- if the event source
131 is a button within a panel within a frame, this will still work, because event
132 tables are searched up through the hierarchy of windows for the command events
133 (but only command events, so you can't catch mouse move events in a child
134 control in the parent window in the same way because wxMouseEvent doesn't
135 derive from wxCommandEvent, see below for how you can do it). In this case, the
136 button's event table will be searched, then the parent panel's, then the
137 frame's.
138
139 Finally, you need to implement the event handlers. As mentioned before, all
140 event handlers take a wxEvent-derived argument whose exact class differs
141 according to the type of event and the class of the originating window. For
142 size events, wxSizeEvent is used. For menu commands and most control commands
143 (such as button presses), wxCommandEvent is used. And when controls get more
144 complicated, more specific wxCommandEvent-derived event classes providing
145 additional control-specific information can be used, such as wxTreeEvent for
146 events from wxTreeCtrl windows.
147
148 In the simplest possible case an event handler may not use the @c event
149 parameter at all, e.g.
150
151 @code
152 void MyFrame::OnExit(wxCommandEvent&)
153 {
154 // when the user selects "Exit" from the menu we should close
155 Close(true);
156 }
157 @endcode
158
159 In other cases you may need some information carried by the @c event argument,
160 as in:
161
162 @code
163 void MyFrame::OnSize(wxSizeEvent& event)
164 {
165 wxSize size = event.GetSize();
166
167 ... update the frame using the new size ...
168 }
169 @endcode
170
171 You will find the details about the event table macros and the corresponding
172 wxEvent-derived classes in the discussion of each control generating these
173 events.
174
175
176 @section overview_eventhandling_connect Dynamic Event Handling
177
178 As with the event tables, you need to decide in which class do you intend to
179 handle the events first and, also as before, this class must still derive from
180 wxEvtHandler (usually indirectly via wxWindow), see the declaration of MyFrame
181 in the previous section. However the similarities end here and both the syntax
182 and the possibilities of this way of handling events in this way are rather
183 different.
184
185 Let us start by looking at the syntax: the first obvious difference is that you
186 don't need to use neither @c DECLARE_EVENT_TABLE() nor @c BEGIN_EVENT_TABLE and
187 associated macros any more. Instead, in any place in your code, but usually in
188 the code of the class defining the handlers itself (and definitely not in the
189 global scope as with the event tables), you should call its Connect() method
190 like this:
191
192 @code
193 MyFrame::MyFrame(...)
194 {
195 Connect(wxID_EXIT, wxEVT_COMMAND_MENU_SELECTED,
196 wxCommandEventHandler(MyFrame::OnExit));
197 }
198 @endcode
199
200 This class should be self-explanatory except for wxCommandEventHandler part:
201 this is a macro which ensures that the method is of correct type by using
202 static_cast in the same way as event table macros do it inside them.
203
204 Now let us describe the semantic differences:
205 <ul>
206 <li>
207 Event handlers can be connected at any moment, e.g. it's possible to do
208 some initialization first and only connect the handlers if and when it
209 succeeds. This can avoid the need to test that the object was properly
210 initialized in the event handlers themselves: with Connect() they
211 simply won't be called at all if it wasn't.
212 </li>
213
214 <li>
215 As a slight extension of the above, the handlers can also be
216 Disconnect()-ed at any time. And maybe later reconnected again. Of
217 course, it's also possible to emulate this behaviour with the classic
218 static (i.e. connected via event tables) handlers by using an internal
219 flag indicating whether the handler is currently enabled and returning
220 from it if it isn't, but using dynamically connected handlers requires
221 less code and is also usually more clear.
222 </li>
223
224 <li>
225 Also notice that you must derive a class inherited from, say,
226 wxTextCtrl even if you don't want to modify the control behaviour at
227 all but just want to handle some of its events. This is especially
228 inconvenient when the control is loaded from the XRC. Connecting the
229 event handler dynamically bypasses the need for this unwanted
230 sub-classing.
231 </li>
232
233 <li>
234 Last but very, very far from least is the possibility to connect an
235 event of some object to a method of another object. This is impossible
236 to do with event tables because there is no possibility to specify the
237 object to dispatch the event to so it necessarily needs to be sent to
238 the same object which generated the event. Not so with Connect() which
239 has an optional @c eventSink parameter which can be used to specify the
240 object which will handle the event. Of course, in this case the method
241 being connected must belong to the class which is the type of the
242 @c eventSink object! To give a quick example, people often want to catch
243 mouse movement events happening when the mouse is in one of the frame
244 children in the frame itself. Doing it in a naive way doesn't work:
245 <ul>
246 <li>
247 A @c EVT_LEAVE_WINDOW(MyFrame::OnMouseLeave) line in the frame
248 event table has no effect as mouse move (including entering and
249 leaving) events are not propagated upwards to the parent window
250 (at least not by default).
251 </li>
252
253 <li>
254 Putting the same line in a child event table will crash during
255 run-time because the MyFrame method will be called on a wrong
256 object -- it's easy to convince oneself that the only object
257 which can be used here is the pointer to the child, as
258 wxWidgets has nothing else. But calling a frame method with the
259 child window pointer instead of the pointer to the frame is, of
260 course, disastrous.
261 </li>
262 </ul>
263
264 However writing
265 @code
266 MyFrame::MyFrame(...)
267 {
268 m_child->Connect(wxID_ANY, wxEVT_LEAVE_WINDOW,
269 wxMouseEventHandler(MyFrame::OnMouseLeave),
270 NULL, // unused extra data parameter
271 this); // this indicates the object to connect to
272 }
273 @endcode
274 will work exactly as expected. Note that you can get the object which
275 generated the event -- and which is not the same as the frame -- via
276 wxEvent::GetEventObject() method of @c event argument passed to the
277 event handler.
278 <li>
279 </ul>
280
281 To summarize, using Connect() requires slightly more typing but is much more
282 flexible than using static event tables so don't hesitate to use it when you
283 need this extra power. On the other hand, event tables are still perfectly fine
284 in simple situations where this extra flexibility is not needed.
285
286
287 @section overview_eventhandling_processing How Events are Processed
288
289 When an event is received from the windowing system, wxWidgets calls
290 wxEvtHandler::ProcessEvent on the first
291 event handler object belonging to the window generating the event.
292
293 It may be noted that wxWidgets' event processing system implements something
294 very close to virtual methods in normal C++, i.e. it is possible to alter
295 the behaviour of a class by overriding its event handling functions. In
296 many cases this works even for changing the behaviour of native controls.
297
298 For example it is possible to filter out a number of key events sent by the
299 system to a native text control by overriding wxTextCtrl and defining a
300 handler for key events using EVT_KEY_DOWN. This would indeed prevent
301 any key events from being sent to the native control - which might not be
302 what is desired. In this case the event handler function has to call Skip()
303 so as to indicate that the search for the event handler should continue.
304
305 To summarize, instead of explicitly calling the base class version as you
306 would have done with C++ virtual functions (i.e. @e wxTextCtrl::OnChar()),
307 you should instead call wxEvent::Skip.
308
309 In practice, this would look like this if the derived text control only
310 accepts 'a' to 'z' and 'A' to 'Z':
311
312 @code
313 void MyTextCtrl::OnChar(wxKeyEvent& event)
314 {
315 if ( isalpha( event.KeyCode() ) )
316 {
317 // key code is within legal range. we call event.Skip() so the
318 // event can be processed either in the base wxWidgets class
319 // or the native control.
320
321 event.Skip();
322 }
323 else
324 {
325 // illegal key hit. we don't call event.Skip() so the
326 // event is not processed anywhere else.
327
328 wxBell();
329 }
330 }
331 @endcode
332
333 The normal order of event table searching by ProcessEvent is as follows:
334
335 @li If the object is disabled (via a call to wxEvtHandler::SetEvtHandlerEnabled)
336 the function skips to step (6).
337 @li If the object is a wxWindow, @b ProcessEvent is recursively called on the window's
338 wxValidator. If this returns @true, the function exits.
339 @li @b SearchEventTable is called for this event handler. If this fails, the base
340 class table is tried, and so on until no more tables exist or an appropriate
341 function was found, in which case the function exits.
342 @li The search is applied down the entire chain of event handlers (usually the chain has
343 a length of one). If this succeeds, the function exits.
344 @li If the object is a wxWindow and the event is set to set to propagate (in the library only
345 wxCommandEvent based events are set to propagate), @b ProcessEvent is recursively applied
346 to the parent window's event handler. If this returns @true, the function exits.
347 @li Finally, @b ProcessEvent is called on the wxApp object.
348
349 <b>Pay close attention to Step 5</b>. People often overlook or get
350 confused by this powerful feature of the wxWidgets event processing
351 system. To put it a different way, events set to propagate
352 (see wxEvent::ShouldPropagate)
353 (most likely derived either directly or indirectly from wxCommandEvent)
354 will travel up the containment hierarchy from child to parent until the
355 maximal propagation level is reached or an event handler is found that
356 doesn't call @c event.Skip().
357
358 Finally, there is another additional complication (which, in fact, simplifies
359 life of wxWidgets programmers significantly): when propagating the command
360 events upwards to the parent window, the event propagation stops when it
361 reaches the parent dialog, if any. This means that you don't risk to get
362 unexpected events from the dialog controls (which might be left unprocessed by
363 the dialog itself because it doesn't care about them) when a modal dialog is
364 popped up. The events do propagate beyond the frames, however. The rationale
365 for this choice is that there are only a few frames in a typical application
366 and their parent-child relation are well understood by the programmer while it
367 may be very difficult, if not impossible, to track down all the dialogs which
368 may be popped up in a complex program (remember that some are created
369 automatically by wxWidgets). If you need to specify a different behaviour for
370 some reason, you can use wxWindow::SetExtraStyle(wxWS_EX_BLOCK_EVENTS)
371 explicitly to prevent the events from being propagated beyond the given window
372 or unset this flag for the dialogs which have it on by default.
373
374 Typically events that deal with a window as a window (size, motion,
375 paint, mouse, keyboard, etc.) are sent only to the window. Events
376 that have a higher level of meaning and/or are generated by the window
377 itself, (button click, menu select, tree expand, etc.) are command
378 events and are sent up to the parent to see if it is interested in the event.
379
380 Note that your application may wish to override ProcessEvent to redirect processing of
381 events. This is done in the document/view framework, for example, to allow event handlers
382 to be defined in the document or view. To test for command events (which will probably
383 be the only events you wish to redirect), you may use wxEvent::IsCommandEvent for efficiency,
384 instead of using the slower run-time type system.
385
386 As mentioned above, only command events are recursively applied to the parents event
387 handler in the library itself. As this quite often causes confusion for users,
388 here is a list of system events which will NOT get sent to the parent's event handler:
389
390 @li wxEvent: The event base class
391 @li wxActivateEvent: A window or application activation event
392 @li wxCloseEvent: A close window or end session event
393 @li wxEraseEvent: An erase background event
394 @li wxFocusEvent: A window focus event
395 @li wxKeyEvent: A keypress event
396 @li wxIdleEvent: An idle event
397 @li wxInitDialogEvent: A dialog initialisation event
398 @li wxJoystickEvent: A joystick event
399 @li wxMenuEvent: A menu event
400 @li wxMouseEvent: A mouse event
401 @li wxMoveEvent: A move event
402 @li wxPaintEvent: A paint event
403 @li wxQueryLayoutInfoEvent: Used to query layout information
404 @li wxSetCursorEvent: Used for special cursor processing based on current mouse position
405 @li wxSizeEvent: A size event
406 @li wxScrollWinEvent: A scroll event sent by a scrolled window (not a scroll bar)
407 @li wxSysColourChangedEvent: A system colour change event
408
409 In some cases, it might be desired by the programmer to get a certain number
410 of system events in a parent window, for example all key events sent to, but not
411 used by, the native controls in a dialog. In this case, a special event handler
412 will have to be written that will override ProcessEvent() in order to pass
413 all events (or any selection of them) to the parent window.
414
415
416 @section overview_eventhandling_prog User Generated Events vs Programmatically Generated Events
417
418 While generically wxEvents can be generated both by user
419 actions (e.g. resize of a wxWindow) and by calls to functions
420 (e.g. wxWindow::SetSize), wxWidgets controls normally send wxCommandEvent-derived
421 events only for the user-generated events. The only @b exceptions to this rule are:
422
423 @li wxNotebook::AddPage: No event-free alternatives
424 @li wxNotebook::AdvanceSelection: No event-free alternatives
425 @li wxNotebook::DeletePage: No event-free alternatives
426 @li wxNotebook::SetSelection: Use wxNotebook::ChangeSelection instead, as
427 wxNotebook::SetSelection is deprecated
428 @li wxTreeCtrl::Delete: No event-free alternatives
429 @li wxTreeCtrl::DeleteAllItems: No event-free alternatives
430 @li wxTreeCtrl::EditLabel: No event-free alternatives
431 @li All wxTextCtrl methods
432
433 wxTextCtrl::ChangeValue can be used instead of wxTextCtrl::SetValue but the other
434 functions, such as wxTextCtrl::Replace or wxTextCtrl::WriteText don't have event-free
435 equivalents.
436
437
438
439 @section overview_eventhandling_pluggable Pluggable Event Handlers
440
441 In fact, you don't have to derive a new class from a window class
442 if you don't want to. You can derive a new class from wxEvtHandler instead,
443 defining the appropriate event table, and then call wxWindow::SetEventHandler
444 (or, preferably, wxWindow::PushEventHandler) to make this
445 event handler the object that responds to events. This way, you can avoid
446 a lot of class derivation, and use instances of the same event handler class (but different
447 objects as the same event handler object shouldn't be used more than once) to
448 handle events from instances of different widget classes.
449
450 If you ever have to call a window's event handler
451 manually, use the GetEventHandler function to retrieve the window's event handler and use that
452 to call the member function. By default, GetEventHandler returns a pointer to the window itself
453 unless an application has redirected event handling using SetEventHandler or PushEventHandler.
454
455 One use of PushEventHandler is to temporarily or permanently change the
456 behaviour of the GUI. For example, you might want to invoke a dialog editor
457 in your application that changes aspects of dialog boxes. You can
458 grab all the input for an existing dialog box, and edit it 'in situ',
459 before restoring its behaviour to normal. So even if the application
460 has derived new classes to customize behaviour, your utility can indulge
461 in a spot of body-snatching. It could be a useful technique for on-line
462 tutorials, too, where you take a user through a serious of steps and
463 don't want them to diverge from the lesson. Here, you can examine the events
464 coming from buttons and windows, and if acceptable, pass them through to
465 the original event handler. Use PushEventHandler/PopEventHandler
466 to form a chain of event handlers, where each handler processes a different
467 range of events independently from the other handlers.
468
469
470
471 @section overview_eventhandling_winid Window Identifiers
472
473 Window identifiers are integers, and are used to
474 uniquely determine window identity in the event system (though you can use it
475 for other purposes). In fact, identifiers do not need to be unique
476 across your entire application just so long as they are unique within a
477 particular context you're interested in, such as a frame and its children. You
478 may use the @c wxID_OK identifier, for example, on any number of dialogs so
479 long as you don't have several within the same dialog.
480
481 If you pass @c wxID_ANY to a window constructor, an identifier will be
482 generated for you automatically by wxWidgets. This is useful when you don't
483 care about the exact identifier either because you're not going to process the
484 events from the control being created at all or because you process the events
485 from all controls in one place (in which case you should specify @c wxID_ANY
486 in the event table or wxEvtHandler::Connect call
487 as well. The automatically generated identifiers are always negative and so
488 will never conflict with the user-specified identifiers which must be always
489 positive.
490
491 See @ref page_stdevtid for the list of standard identifiers availabel.
492 You can use wxID_HIGHEST to determine the number above which it is safe to
493 define your own identifiers. Or, you can use identifiers below wxID_LOWEST.
494 Finally, you can allocate identifiers dynamically using wxNewId() function to.
495 If you use wxNewId() consistently in your application, you can be sure that
496 the your identifiers don't conflict accidentally.
497
498
499 @section overview_eventhandling_custom Custom Event Summary
500
501 @subsection overview_eventhandling_custom_general General approach
502
503 Since version 2.2.x of wxWidgets, each event type is identified by ID which
504 is given to the event type @e at runtime which makes it possible to add
505 new event types to the library or application without risking ID clashes
506 (two different event types mistakingly getting the same event ID). This
507 event type ID is stored in a struct of type @b const wxEventType.
508
509 In order to define a new event type, there are principally two choices.
510 One is to define a entirely new event class (typically deriving from
511 wxEvent or wxCommandEvent.
512
513 The other is to use the existing event classes and give them an new event
514 type. You'll have to define and declare a new event type using either way,
515 and this is done using the following macros:
516
517 @code
518 // in the header of the source file
519 BEGIN_DECLARE_EVENT_TYPES()
520 DECLARE_EVENT_TYPE(name, value)
521 END_DECLARE_EVENT_TYPES()
522
523 // in the implementation
524 DEFINE_EVENT_TYPE(name)
525 @endcode
526
527 You can ignore the @e value parameter of the DECLARE_EVENT_TYPE macro
528 since it is used only for backwards compatibility with wxWidgets 2.0.x based
529 applications where you have to give the event type ID an explicit value.
530 See also the @ref page_samples_event for an example of code
531 defining and working with the custom event types.
532
533
534 @subsection overview_eventhandling_custom_existing Using Existing Event Classes
535
536 If you just want to use a wxCommandEvent with
537 a new event type, you can then use one of the generic event table macros
538 listed below, without having to define a new macro yourself. This also
539 has the advantage that you won't have to define a new wxEvent::Clone()
540 method for posting events between threads etc. This could look like this
541 in your code:
542
543 @code
544 DECLARE_EVENT_TYPE(wxEVT_MY_EVENT, -1)
545 DEFINE_EVENT_TYPE(wxEVT_MY_EVENT)
546
547 // user code intercepting the event
548
549 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
550 EVT_MENU (wxID_EXIT, MyFrame::OnExit)
551 // ....
552 EVT_COMMAND (ID_MY_WINDOW, wxEVT_MY_EVENT, MyFrame::OnMyEvent)
553 END_EVENT_TABLE()
554
555 void MyFrame::OnMyEvent( wxCommandEvent )
556 {
557 // do something
558 wxString text = event.GetText();
559 }
560
561
562 // user code sending the event
563
564 void MyWindow::SendEvent()
565 {
566 wxCommandEvent event( wxEVT_MY_EVENT, GetId() );
567 event.SetEventObject( this );
568 // Give it some contents
569 event.SetText( wxT("Hallo") );
570 // Send it
571 GetEventHandler()->ProcessEvent( event );
572 }
573 @endcode
574
575
576 @subsection overview_eventhandling_custom_generic Generic Event Table Macros
577
578 @beginTable
579 @row2col{EVT_CUSTOM(event\, id\, func),
580 Allows you to add a custom event table
581 entry by specifying the event identifier (such as wxEVT_SIZE),
582 the window identifier, and a member function to call.}
583 @row2col{EVT_CUSTOM_RANGE(event\, id1\, id2\, func),
584 The same as EVT_CUSTOM, but responds to a range of window identifiers.}
585 @row2col{EVT_COMMAND(id\, event\, func),
586 The same as EVT_CUSTOM, but expects a member function with a
587 wxCommandEvent argument.}
588 @row2col{EVT_COMMAND_RANGE(id1\, id2\, event\, func),
589 The same as EVT_CUSTOM_RANGE, but
590 expects a member function with a wxCommandEvent argument.}
591 @row2col{EVT_NOTIFY(event\, id\, func),
592 The same as EVT_CUSTOM, but
593 expects a member function with a wxNotifyEvent argument.}
594 @row2col{EVT_NOTIFY_RANGE(event\, id1\, id2\, func),
595 The same as EVT_CUSTOM_RANGE, but
596 expects a member function with a wxNotifyEvent argument.}
597 @endTable
598
599
600 @subsection overview_eventhandling_custom_ownclass Defining Your Own Event Class
601
602 Under certain circumstances, it will be required to define your own event
603 class e.g. for sending more complex data from one place to another. Apart
604 from defining your event class, you will also need to define your own
605 event table macro (which is quite long). Watch out to put in enough
606 casts to the inherited event function. Here is an example:
607
608 @code
609 // code defining event
610
611 class wxPlotEvent: public wxNotifyEvent
612 {
613 public:
614 wxPlotEvent( wxEventType commandType = wxEVT_NULL, int id = 0 );
615
616 // accessors
617 wxPlotCurve *GetCurve()
618 { return m_curve; }
619
620 // required for sending with wxPostEvent()
621 virtual wxEvent *Clone() const;
622
623 private:
624 wxPlotCurve *m_curve;
625 };
626
627 DECLARE_EVENT_TYPE( wxEVT_PLOT_ACTION, -1 )
628
629 typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&);
630
631 #define EVT_PLOT(id, fn) \
632 DECLARE_EVENT_TABLE_ENTRY( wxEVT_PLOT_ACTION, id, -1, \
633 (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) \
634 wxStaticCastEvent( wxPlotEventFunction, &fn ), (wxObject *) NULL ),
635
636
637 // code implementing the event type and the event class
638
639 DEFINE_EVENT_TYPE( wxEVT_PLOT_ACTION )
640
641 wxPlotEvent::wxPlotEvent( ...
642
643
644 // user code intercepting the event
645
646 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
647 EVT_PLOT (ID_MY_WINDOW, MyFrame::OnPlot)
648 END_EVENT_TABLE()
649
650 void MyFrame::OnPlot( wxPlotEvent &event )
651 {
652 wxPlotCurve *curve = event.GetCurve();
653 }
654
655
656 // user code sending the event
657
658 void MyWindow::SendEvent()
659 {
660 wxPlotEvent event( wxEVT_PLOT_ACTION, GetId() );
661 event.SetEventObject( this );
662 event.SetCurve( m_curve );
663 GetEventHandler()->ProcessEvent( event );
664 }
665 @endcode
666
667
668 @section overview_eventhandling_macros Event Handling Summary
669
670 For the full list of event classes, please see the
671 @ref group_class_events "event classes group page".
672
673
674 @todo for all controls state clearly when calling a member function results in an
675 event being generated and when it doesn't (possibly updating also the
676 'Events generated by the user vs programmatically generated events' paragraph
677 of the 'Event handling overview' with the list of the functions which break
678 that rule).
679
680 */
681