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