From 4475b41041fc84c370f108f1118d66a655617a5a Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sat, 7 Feb 2009 16:07:59 +0000 Subject: [PATCH] update custom event definition documentation; document wxDEFINE/DECLARE_EVENT() git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@58715 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/doxygen/overviews/eventhandling.h | 211 +++++++++++++------------ interface/wx/event.h | 111 +++++++++++++ 2 files changed, 220 insertions(+), 102 deletions(-) diff --git a/docs/doxygen/overviews/eventhandling.h b/docs/doxygen/overviews/eventhandling.h index f4ecda8f88..0e4c7f2392 100644 --- a/docs/doxygen/overviews/eventhandling.h +++ b/docs/doxygen/overviews/eventhandling.h @@ -478,170 +478,152 @@ all events (or any selection of them) to the parent window. @subsection overview_events_custom_general General approach -Since version 2.2.x of wxWidgets, each event type is identified by an ID -given to the event type @e at runtime that makes it possible to add -new event types to the library or application without risking ID clashes -(two different event types mistakingly getting the same event ID). -This event type ID is stored in a struct of type const wxEventType. +As each event is uniquely defined by its event type, defining a custom event +starts with defining a new event type for it. This is done using +wxDEFINE_EVENT() macro. As an event type is a variable, it can also be +declared using wxDECLARE_EVENT() if necessary. -In order to define a new event type, there are principally two choices. -One is to define an entirely new event class (typically deriving from -wxEvent or wxCommandEvent). - -The other is to use the existing event classes and give them a new event -type. You'll have to define and declare a new event type either way -using the following macros: - -@code -// in the header of the source file -extern const wxEventType wxEVT_YOUR_EVENT_NAME; - -// in the implementation -DEFINE_EVENT_TYPE(wxEVT_YOUR_EVENT_NAME) -@endcode - -See also the @ref page_samples_event for an example of code -defining and working with the custom event types. +The next thing to do is to decide whether you need to define a custom event +class for events of this type or if you can reuse an existing class, typically +either wxEvent (which doesn't provide any extra information) or wxCommandEvent +(which contains several extra fields and also propagates upwards by default). +Both strategies are described in details below. See also the @ref +page_samples_event for a complete example of code defining and working with the +custom event types. @subsection overview_events_custom_existing Using Existing Event Classes -If you just want to use a wxCommandEvent with a new event type, use -one of the generic event table macros listed below, without having to define a -new event class yourself. This also has the advantage that you won't have to define a -new wxEvent::Clone() method for posting events between threads etc. +If you just want to use a wxCommandEvent with a new event type, use one of the +generic event table macros listed below, without having to define a new event +class yourself. Example: @code -extern const wxEventType wxEVT_MY_EVENT; -DEFINE_EVENT_TYPE(wxEVT_MY_EVENT) +// this is typically in a header: it just declares MY_EVENT event type +wxDECLARE_EVENT(MY_EVENT, wxCommandEvent); -// user code intercepting the event +// this is a definition so can't be in a header +wxDEFINE_EVENT(MY_EVENT, wxCommandEvent); +// example of code handling the event with event tables BEGIN_EVENT_TABLE(MyFrame, wxFrame) -EVT_MENU (wxID_EXIT, MyFrame::OnExit) -// .... -EVT_COMMAND (ID_MY_WINDOW, wxEVT_MY_EVENT, MyFrame::OnMyEvent) + EVT_MENU (wxID_EXIT, MyFrame::OnExit) + ... + EVT_COMMAND (ID_MY_WINDOW, MY_EVENT, MyFrame::OnMyEvent) END_EVENT_TABLE() -void MyFrame::OnMyEvent( wxCommandEvent& event ) +void MyFrame::OnMyEvent(wxCommandEvent& event) { // do something wxString text = event.GetText(); } +// example of code handling the event with Connect(): +MyFrame::MyFrame() +{ + Connect(ID_MY_WINDOW, MY_EVENT, &MyFrame::OnMyEvent); +} -// user code sending the event - +// example of code generating the event void MyWindow::SendEvent() { - wxCommandEvent event( wxEVT_MY_EVENT, GetId() ); - event.SetEventObject( this ); + wxCommandEvent event(MY_EVENT, GetId()); + event.SetEventObject(this); // Give it some contents - event.SetText( wxT("Hallo") ); + event.SetText("Hello"); - // Send it - GetEventHandler()->ProcessEvent( event ); + // Do send it + ProcessWindowEvent(event); } @endcode -@subsection overview_events_custom_generic Generic Event Table Macros - -@beginTable -@row2col{EVT_CUSTOM(event\, id\, func), - Allows you to add a custom event table - entry by specifying the event identifier (such as wxEVT_SIZE), - the window identifier, and a member function to call.} -@row2col{EVT_CUSTOM_RANGE(event\, id1\, id2\, func), - The same as EVT_CUSTOM, but responds to a range of window identifiers.} -@row2col{EVT_COMMAND(id\, event\, func), - The same as EVT_CUSTOM, but expects a member function with a - wxCommandEvent argument.} -@row2col{EVT_COMMAND_RANGE(id1\, id2\, event\, func), - The same as EVT_CUSTOM_RANGE, but - expects a member function with a wxCommandEvent argument.} -@row2col{EVT_NOTIFY(event\, id\, func), - The same as EVT_CUSTOM, but - expects a member function with a wxNotifyEvent argument.} -@row2col{EVT_NOTIFY_RANGE(event\, id1\, id2\, func), - The same as EVT_CUSTOM_RANGE, but - expects a member function with a wxNotifyEvent argument.} -@endTable - - @subsection overview_events_custom_ownclass Defining Your Own Event Class -Under certain circumstances, you must define your own event -class e.g., for sending more complex data from one place to another. Apart -from defining your event class, you will also need to define your own -event table macro (which is quite long). Watch out to put in enough -casts to the inherited event function. Here is an example: +Under certain circumstances, you must define your own event class e.g., for +sending more complex data from one place to another. Apart from defining your +event class, you also need to define your own event table macro if you want to +use event tables for handling events of this type. -@code -// code defining event +Here is an example: -class wxPlotEvent: public wxNotifyEvent +@code +// define a new event class +class MyPlotEvent: public wxEvent { public: - wxPlotEvent( wxEventType commandType = wxEVT_NULL, int id = 0 ); + MyPlotEvent(wxEventType eventType, int winid, const wxPoint& pos) + : wxEvent(winid, eventType), + m_pos(pos) + { + } // accessors - wxPlotCurve *GetCurve() - { return m_curve; } + wxPoint GetPoint() const { return m_pos; } - // required for sending with wxPostEvent() - virtual wxEvent *Clone() const; + // implement the base class pure virtual + virtual wxEvent *Clone() const { return new MyPlotEvent(*this); } private: - wxPlotCurve *m_curve; + const wxPoint m_pos; }; -extern const wxEventType wxEVT_PLOT_ACTION; -typedef void (wxEvtHandler::*wxPlotEventFunction)(wxPlotEvent&); - -#define wxPlotEventHandler(func) \ - (wxObjectEventFunction)(wxEventFunction)wxStaticCastEvent(wxPlotEventFunction, &func) -#define EVT_PLOT(id, fn) \ - wx__DECLARE_EVT1(wxEVT_PLOT_ACTION, id, wxPlotEventHandler(fn)) +// we define a single MY_PLOT_CLICKED event type associated with the class +// above but typically you are going to have more than one event type, e.g. you +// could also have MY_PLOT_ZOOMED or MY_PLOT_PANNED &c -- in which case you +// would just add more similar lines here +wxDEFINE_EVENT(MY_PLOT_CLICKED, MyPlotEvent); -// code implementing the event type and the event class +// if you want to support old compilers you need to use some ugly macros: +typedef void (wxEvtHandler::*MyPlotEventFunction)(MyPlotEvent&); +#define MyPlotEventHandler(func) wxEVENT_HANDLER_CAST(MyPlotEventFunction, func) -DEFINE_EVENT_TYPE( wxEVT_PLOT_ACTION ) +// if your code is only built sing reasonably modern compilers, you could just +// do this instead: +#define MyPlotEventHandler(func) (&func) -wxPlotEvent::wxPlotEvent( ... ) -{ - ... -} +// finally define a macro for creating the event table entries for the new +// event type +// +// remember that you don't need this at all if you only use Connect() and that +// you can replace MyPlotEventHandler(func) with just &func unless you use a +// really old compiler +#define MY_EVT_PLOT_CLICK(id, func) \ + wx__DECLARE_EVT1(MY_PLOT_CLICKED, id, MyPlotEventHandler(func)) -// user code intercepting the event - +// example of code handling the event (you will use one of these methods, not +// both, of course): BEGIN_EVENT_TABLE(MyFrame, wxFrame) -EVT_PLOT (ID_MY_WINDOW, MyFrame::OnPlot) + EVT_PLOT(ID_MY_WINDOW, MyFrame::OnPlot) END_EVENT_TABLE() -void MyFrame::OnPlot( wxPlotEvent &event ) +MyFrame::MyFrame() { - wxPlotCurve *curve = event.GetCurve(); + Connect(ID_MY_WINDOW, MY_PLOT_CLICKED, &MyFrame::OnPlot); } +void MyFrame::OnPlot(MyPlotEvent& event) +{ + ... do something with event.GetPoint() ... +} -// user code sending the event +// example of code generating the event: void MyWindow::SendEvent() { - wxPlotEvent event( wxEVT_PLOT_ACTION, GetId() ); - event.SetEventObject( this ); - event.SetCurve( m_curve ); - GetEventHandler()->ProcessEvent( event ); + MyPlotEvent event(MY_PLOT_CLICKED, GetId(), wxPoint(...)); + event.SetEventObject(this); + ProcessWindowEvent(event); } @endcode + @section overview_events_misc Miscellaneous Notes @subsection overview_events_virtual Event Handlers vs Virtual Methods @@ -755,6 +737,31 @@ If you use wxNewId() consistently in your application, you can be sure that your identifiers don't conflict accidentally. +@subsection overview_events_custom_generic Generic Event Table Macros + +@beginTable +@row2col{EVT_CUSTOM(event\, id\, func), + Allows you to add a custom event table + entry by specifying the event identifier (such as wxEVT_SIZE), + the window identifier, and a member function to call.} +@row2col{EVT_CUSTOM_RANGE(event\, id1\, id2\, func), + The same as EVT_CUSTOM, but responds to a range of window identifiers.} +@row2col{EVT_COMMAND(id\, event\, func), + The same as EVT_CUSTOM, but expects a member function with a + wxCommandEvent argument.} +@row2col{EVT_COMMAND_RANGE(id1\, id2\, event\, func), + The same as EVT_CUSTOM_RANGE, but + expects a member function with a wxCommandEvent argument.} +@row2col{EVT_NOTIFY(event\, id\, func), + The same as EVT_CUSTOM, but + expects a member function with a wxNotifyEvent argument.} +@row2col{EVT_NOTIFY_RANGE(event\, id1\, id2\, func), + The same as EVT_CUSTOM_RANGE, but + expects a member function with a wxNotifyEvent argument.} +@endTable + + + @subsection overview_events_macros Event Handling Summary For the full list of event classes, please see the diff --git a/interface/wx/event.h b/interface/wx/event.h index 6cc3654406..030d3415f6 100644 --- a/interface/wx/event.h +++ b/interface/wx/event.h @@ -3497,14 +3497,125 @@ wxEventType wxEVT_NULL; /** Initializes a new event type using wxNewEventType(). + + @deprecated Use wxDEFINE_EVENT() instead */ #define DEFINE_EVENT_TYPE(name) const wxEventType name = wxNewEventType(); /** Generates a new unique event type. + + Usually this function is only used by wxDEFINE_EVENT() and not called + directly. */ wxEventType wxNewEventType(); +/** + Define a new event type associated with the specified event class. + + This macro defines a new unique event type @a name associated with the + event class @a cls. + + For example: + @code + wxDEFINE_EVENT(MY_COMMAND_EVENT, wxCommandEvent); + + class MyCustomEvent : public wxEvent { ... }; + wxDEFINE_EVENT(MY_CUSTOM_EVENT, MyCustomEvent); + @endcode + + @see wxDECLARE_EVENT(), @ref overview_events_custom + */ +#define wxDEFINE_EVENT(name, cls) \ + const wxEventTypeTag< cls > name(wxNewEventType()) + +/** + Declares a custom event type. + + This macro declares a variable called @a name which must be defined + elsewhere using wxDEFINE_EVENT(). + + The class @a cls must be the wxEvent-derived class associated with the + events of this type and its full declaration must be visible from the point + of use of this macro. + */ +#define wxDECLARE_EVENT(name, cls) \ + wxDECLARE_EXPORTED_EVENT(wxEMPTY_PARAMETER_VALUE, name, cls) + +/** + Variant of wxDECLARE_EVENT() used for event types defined inside a shared + library. + + This is mostly used by wxWidgets internally, e.g. + @code + wxDECLARE_EXPORTED_EVENT(WXDLLIMPEXP_CORE, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEvent) + @endcode + */ +#define wxDECLARE_EXPORTED_EVENT( expdecl, name, cls ) \ + extern const expdecl wxEventTypeTag< cls > name; + +/** + Helper macro for definition of custom event table macros. + + This macro must only be used if wxEVENTS_COMPATIBILITY_2_8 is 1, otherwise + it is better and more clear to just use the address of the function + directly as this is all this macro does in this case. However it needs to + explicitly cast @a func to @a functype, which is the type of wxEvtHandler + member function taking the custom event argument when + wxEVENTS_COMPATIBILITY_2_8 is 0. + + See wx__DECLARE_EVT0 for an example of use. + + @see @ref overview_events_custom_ownclass + */ +#define wxEVENT_HANDLER_CAST(functype, func) (&func) + +//@{ +/** + These macros are used to define event table macros for handling custom + events. + + Example of use: + @code + class MyEvent : public wxEvent { ... }; + + // note that this is not necessary unless using old compilers: for the + // reasonably new ones just use &func instead of MyEventHandler(func) + typedef void (wxEvtHandler::*MyEventFunction)(MyEvent&); + #define MyEventHandler(func) wxEVENT_HANDLER_CAST(MyEventFunction, func) + + wxDEFINE_EVENT(MY_EVENT_TYPE, MyEvent); + + #define EVT_MY(id, func) \ + wx__DECLARE_EVT1(MY_EVENT_TYPE, id, MyEventHandler(func)) + + ... + + BEGIN_EVENT_TABLE(MyFrame, wxFrame) + EVT_MY(wxID_ANY, MyFrame::OnMyEvent) + END_EVENT_TABLE() + @endcode + + @param evt + The event type to handle. + @param id + The identifier of events to handle. + @param id1 + The first identifier of the range. + @param id2 + The second identifier of the range. + @param fn + The event handler method. + */ +#define wx__DECLARE_EVT2(evt, id1, id2, fn) \ + DECLARE_EVENT_TABLE_ENTRY(evt, id1, id2, fn, NULL), +#define wx__DECLARE_EVT1(evt, id, fn) \ + wx__DECLARE_EVT2(evt, id, wxID_ANY, fn) +#define wx__DECLARE_EVT0(evt, fn) \ + wx__DECLARE_EVT1(evt, wxID_ANY, fn) +//@} + + /** Use this macro inside a class declaration to declare a @e static event table for that class. -- 2.45.2