]>
Commit | Line | Data |
---|---|---|
15b6757b | 1 | ///////////////////////////////////////////////////////////////////////////// |
3b88355f | 2 | // Name: eventhandling.h |
15b6757b FM |
3 | // Purpose: topic overview |
4 | // Author: wxWidgets team | |
5 | // RCS-ID: $Id$ | |
6 | // Licence: wxWindows license | |
7 | ///////////////////////////////////////////////////////////////////////////// | |
8 | ||
880efa2a | 9 | /** |
36c9828f | 10 | |
dc28cdf8 FM |
11 | @page overview_eventhandling Event Handling |
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_samples_event for an example of doing it. | |
99 | ||
100 | ||
101 | ||
409e6ce4 | 102 | @section overview_eventhandling_processing How Events are Processed |
dc28cdf8 FM |
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 | { | |
15b6757b FM |
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. | |
36c9828f | 135 | |
15b6757b | 136 | event.Skip(); |
dc28cdf8 FM |
137 | } |
138 | else | |
139 | { | |
15b6757b FM |
140 | // illegal key hit. we don't call event.Skip() so the |
141 | // event is not processed anywhere else. | |
36c9828f | 142 | |
15b6757b | 143 | wxBell(); |
dc28cdf8 FM |
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 | ||
409e6ce4 | 231 | @section overview_eventhandling_prog User Generated Events vs Programmatically Generated Events |
dc28cdf8 FM |
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 | ||
409e6ce4 | 254 | @section overview_eventhandling_pluggable Pluggable Event Handlers |
dc28cdf8 FM |
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 | ||
409e6ce4 | 286 | @section overview_eventhandling_winid Window Identifiers |
dc28cdf8 FM |
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 | See @ref page_stdevtid for the list of standard identifiers availabel. | |
307 | You can use wxID_HIGHEST to determine the number above which it is safe to | |
308 | define your own identifiers. Or, you can use identifiers below wxID_LOWEST. | |
309 | Finally, you can allocate identifiers dynamically using wxNewId() function to. | |
310 | If you use wxNewId() consistently in your application, you can be sure that | |
311 | the your identifiers don't conflict accidentally. | |
312 | ||
313 | ||
409e6ce4 | 314 | @section overview_eventhandling_custom Custom Event Summary |
dc28cdf8 FM |
315 | |
316 | @subsection overview_eventhandling_custom_general General approach | |
317 | ||
318 | Since version 2.2.x of wxWidgets, each event type is identified by ID which | |
319 | is given to the event type @e at runtime which makes it possible to add | |
320 | new event types to the library or application without risking ID clashes | |
321 | (two different event types mistakingly getting the same event ID). This | |
322 | event type ID is stored in a struct of type @b const wxEventType. | |
323 | ||
324 | In order to define a new event type, there are principally two choices. | |
325 | One is to define a entirely new event class (typically deriving from | |
326 | wxEvent or wxCommandEvent. | |
327 | ||
328 | The other is to use the existing event classes and give them an new event | |
329 | type. You'll have to define and declare a new event type using either way, | |
330 | and this is done using the following macros: | |
331 | ||
332 | @code | |
333 | // in the header of the source file | |
334 | BEGIN_DECLARE_EVENT_TYPES() | |
335 | DECLARE_EVENT_TYPE(name, value) | |
336 | END_DECLARE_EVENT_TYPES() | |
337 | ||
338 | // in the implementation | |
339 | DEFINE_EVENT_TYPE(name) | |
340 | @endcode | |
341 | ||
342 | You can ignore the @e value parameter of the DECLARE_EVENT_TYPE macro | |
343 | since it is used only for backwards compatibility with wxWidgets 2.0.x based | |
344 | applications where you have to give the event type ID an explicit value. | |
345 | See also the @ref page_samples_event for an example of code | |
346 | defining and working with the custom event types. | |
347 | ||
348 | ||
409e6ce4 | 349 | @subsection overview_eventhandling_custom_existing Using Existing Event Classes |
dc28cdf8 FM |
350 | |
351 | If you just want to use a wxCommandEvent with | |
352 | a new event type, you can then use one of the generic event table macros | |
353 | listed below, without having to define a new macro yourself. This also | |
354 | has the advantage that you won't have to define a new wxEvent::Clone() | |
355 | method for posting events between threads etc. This could look like this | |
356 | in your code: | |
357 | ||
358 | @code | |
359 | DECLARE_EVENT_TYPE(wxEVT_MY_EVENT, -1) | |
360 | DEFINE_EVENT_TYPE(wxEVT_MY_EVENT) | |
361 | ||
362 | // user code intercepting the event | |
363 | ||
364 | BEGIN_EVENT_TABLE(MyFrame, wxFrame) | |
365 | EVT_MENU (wxID_EXIT, MyFrame::OnExit) | |
366 | // .... | |
367 | EVT_COMMAND (ID_MY_WINDOW, wxEVT_MY_EVENT, MyFrame::OnMyEvent) | |
368 | END_EVENT_TABLE() | |
369 | ||
370 | void MyFrame::OnMyEvent( wxCommandEvent ) | |
371 | { | |
372 | // do something | |
373 | wxString text = event.GetText(); | |
374 | } | |
36c9828f FM |
375 | |
376 | ||
dc28cdf8 | 377 | // user code sending the event |
36c9828f | 378 | |
dc28cdf8 FM |
379 | void MyWindow::SendEvent() |
380 | { | |
381 | wxCommandEvent event( wxEVT_MY_EVENT, GetId() ); | |
382 | event.SetEventObject( this ); | |
383 | // Give it some contents | |
384 | event.SetText( wxT("Hallo") ); | |
385 | // Send it | |
386 | GetEventHandler()->ProcessEvent( event ); | |
387 | } | |
388 | @endcode | |
36c9828f FM |
389 | |
390 | ||
409e6ce4 | 391 | @subsection overview_eventhandling_custom_generic Generic Event Table Macros |
3b88355f | 392 | |
dc28cdf8 FM |
393 | @beginTable |
394 | @row2col{EVT_CUSTOM(event\, id\, func), | |
395 | Allows you to add a custom event table | |
396 | entry by specifying the event identifier (such as wxEVT_SIZE), | |
397 | the window identifier, and a member function to call.} | |
398 | @row2col{EVT_CUSTOM_RANGE(event\, id1\, id2\, func), | |
399 | The same as EVT_CUSTOM, but responds to a range of window identifiers.} | |
400 | @row2col{EVT_COMMAND(id\, event\, func), | |
401 | The same as EVT_CUSTOM, but expects a member function with a | |
402 | wxCommandEvent argument.} | |
403 | @row2col{EVT_COMMAND_RANGE(id1\, id2\, event\, func), | |
404 | The same as EVT_CUSTOM_RANGE, but | |
405 | expects a member function with a wxCommandEvent argument.} | |
406 | @row2col{EVT_NOTIFY(event\, id\, func), | |
407 | The same as EVT_CUSTOM, but | |
408 | expects a member function with a wxNotifyEvent argument.} | |
409 | @row2col{EVT_NOTIFY_RANGE(event\, id1\, id2\, func), | |
410 | The same as EVT_CUSTOM_RANGE, but | |
411 | expects a member function with a wxNotifyEvent argument.} | |
412 | @endTable | |
3b88355f FM |
413 | |
414 | ||
409e6ce4 | 415 | @subsection overview_eventhandling_custom_ownclass Defining Your Own Event Class |
36c9828f | 416 | |
dc28cdf8 FM |
417 | Under certain circumstances, it will be required to define your own event |
418 | class e.g. for sending more complex data from one place to another. Apart | |
419 | from defining your event class, you will also need to define your own | |
420 | event table macro (which is quite long). Watch out to put in enough | |
421 | casts to the inherited event function. Here is an example: | |
36c9828f | 422 | |
dc28cdf8 FM |
423 | @code |
424 | // code defining event | |
36c9828f | 425 | |
dc28cdf8 FM |
426 | class wxPlotEvent: public wxNotifyEvent |
427 | { | |
428 | public: | |
429 | wxPlotEvent( wxEventType commandType = wxEVT_NULL, int id = 0 ); | |
36c9828f | 430 | |
dc28cdf8 FM |
431 | // accessors |
432 | wxPlotCurve *GetCurve() | |
433 | { return m_curve; } | |
36c9828f | 434 | |
dc28cdf8 FM |
435 | // required for sending with wxPostEvent() |
436 | virtual wxEvent *Clone() const; | |
36c9828f | 437 | |
dc28cdf8 FM |
438 | private: |
439 | wxPlotCurve *m_curve; | |
440 | }; | |
36c9828f | 441 | |
dc28cdf8 | 442 | DECLARE_EVENT_TYPE( wxEVT_PLOT_ACTION, -1 ) |
36c9828f | 443 | |
dc28cdf8 | 444 | typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&); |
36c9828f | 445 | |
dc28cdf8 FM |
446 | #define EVT_PLOT(id, fn) \ |
447 | DECLARE_EVENT_TABLE_ENTRY( wxEVT_PLOT_ACTION, id, -1, \ | |
448 | (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction) (wxNotifyEventFunction) \ | |
449 | wxStaticCastEvent( wxPlotEventFunction, &fn ), (wxObject *) NULL ), | |
36c9828f FM |
450 | |
451 | ||
dc28cdf8 | 452 | // code implementing the event type and the event class |
36c9828f | 453 | |
dc28cdf8 | 454 | DEFINE_EVENT_TYPE( wxEVT_PLOT_ACTION ) |
36c9828f | 455 | |
dc28cdf8 | 456 | wxPlotEvent::wxPlotEvent( ... |
36c9828f FM |
457 | |
458 | ||
dc28cdf8 | 459 | // user code intercepting the event |
36c9828f | 460 | |
dc28cdf8 FM |
461 | BEGIN_EVENT_TABLE(MyFrame, wxFrame) |
462 | EVT_PLOT (ID_MY_WINDOW, MyFrame::OnPlot) | |
463 | END_EVENT_TABLE() | |
36c9828f | 464 | |
dc28cdf8 FM |
465 | void MyFrame::OnPlot( wxPlotEvent &event ) |
466 | { | |
467 | wxPlotCurve *curve = event.GetCurve(); | |
468 | } | |
36c9828f FM |
469 | |
470 | ||
dc28cdf8 | 471 | // user code sending the event |
36c9828f | 472 | |
dc28cdf8 FM |
473 | void MyWindow::SendEvent() |
474 | { | |
475 | wxPlotEvent event( wxEVT_PLOT_ACTION, GetId() ); | |
476 | event.SetEventObject( this ); | |
477 | event.SetCurve( m_curve ); | |
478 | GetEventHandler()->ProcessEvent( event ); | |
479 | } | |
480 | @endcode | |
36c9828f | 481 | |
86faa458 | 482 | |
409e6ce4 | 483 | @section overview_eventhandling_macros Event Handling Summary |
86faa458 | 484 | |
dc28cdf8 | 485 | For the full list of event classes, please see the |
409e6ce4 | 486 | @ref group_class_events "event classes group page". |
86faa458 | 487 | |
3b88355f | 488 | */ |
36c9828f | 489 |