Difference between revisions of "Custom Events in wx2.8 and earlier"

From WxWiki
Jump to navigation Jump to search
m (Text replacement - "<source>" to "<syntaxhighlight lang="cpp">")
 
(20 intermediate revisions by 8 users not shown)
Line 1: Line 1:
The information here is provided to supplement the [http://docs.wxwidgets.org/trunk/overview_eventhandling.html#overview_eventhandling_custom Custom Event Summary] which you should read first. Also, it is a good idea to look at the events project in the distribution ''samples'' directory.
+
The information here is provided to supplement the [https://docs.wxwidgets.org/stable/wx_eventhandlingoverview.html#customevents Custom Event Summary] which you should read first. Also, it is a good idea to look at the events project in the distribution ''samples'' directory.
  
 
You may also find the following articles helpful:
 
You may also find the following articles helpful:
* Markus Neifer has written the [[Custom Events Tutorial|Custom Events Tutorial]] for use with wxWidgets 2.3, but most of it should still be relevant.
+
* Markus Neifer has written the [[Custom Events Tutorial|Custom Events Tutorial]] which has been updated to work with wxWidgets 2.8.10.
* HopeSeekr of [http://xmule.ws/ xMule] has composed a [http://www.xmule.ws/phpnuke/modules.php?name=News&amp;file=article&amp;sid=76 tutorial].
 
  
 
== Quick User Notes ==
 
== Quick User Notes ==
Line 13: Line 12:
 
** Send the event to oneself (possibly relying on it to be propagated to the parent).
 
** Send the event to oneself (possibly relying on it to be propagated to the parent).
 
** Send the event to another event handler explicitly associated with us.
 
** Send the event to another event handler explicitly associated with us.
** Send the event to all top level windows (possibly relying on them to propagate the event *downwards* to their children recursively; example: EVT_IDLE).
+
** Send the event to all top level windows (possibly relying on them to propagate the event *downwards* to their children recursively; example: EVT_IDLE) NB. downward propagation of wx events only happens for idle events.
 
** Send the event to wxTheApp only.
 
** Send the event to wxTheApp only.
 
* In sub-classing wxEvent, remember to associate your event (wxFooEvent) to your event type (wxEVT_FOO) in the constructor:
 
* In sub-classing wxEvent, remember to associate your event (wxFooEvent) to your event type (wxEVT_FOO) in the constructor:
<source>
+
<syntaxhighlight lang="cpp">
 
wxFooEvent( int id = 0 )
 
wxFooEvent( int id = 0 )
 
: wxEvent (id, wxEVT_FOO)
 
: wxEvent (id, wxEVT_FOO)
Line 22: Line 21:
 
...
 
...
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
* To get a unique wxEVT_FOO, use:
 
* To get a unique wxEVT_FOO, use:
<source>wxEVT_FOO = wxNewEventType();</source>
+
<syntaxhighlight lang="cpp">wxEVT_FOO = wxNewEventType();</syntaxhighlight>
  
 
== wxEvtHandler::ProcessEvent vs. wxPostEvent and wxEvtHandler::AddPendingEvent ==
 
== wxEvtHandler::ProcessEvent vs. wxPostEvent and wxEvtHandler::AddPendingEvent ==
Line 31: Line 30:
 
These can be used when the event handler object (usually a wxWindow) is known at compile time.
 
These can be used when the event handler object (usually a wxWindow) is known at compile time.
  
<source>wxEvtHandler::ProcessEvent(wxEvent &event)</source>
+
<syntaxhighlight lang="cpp">wxEvtHandler::ProcessEvent(wxEvent &event)</syntaxhighlight>
  
 
<tt>ProcessEvent</tt> will call the event handler directly and the event will be processed immediately, like a function call.
 
<tt>ProcessEvent</tt> will call the event handler directly and the event will be processed immediately, like a function call.
  
<source>wxEvtHandler::AddPendingEvent(wxEvent& event)</source>
+
<syntaxhighlight lang="cpp">wxEvtHandler::AddPendingEvent(wxEvent& event)</syntaxhighlight>
  
<source>wxPostEvent(wxEvtHandler *evtHandler, wxEvent &event)</source>
+
<syntaxhighlight lang="cpp">wxPostEvent(wxEvtHandler *evtHandler, wxEvent &event)</syntaxhighlight>
  
<tt>wxPostEvent</tt> is just a wrapper for wxEvtHandler::AddPendingEvent: '''wxPostEvent(pWindow,event)''' is the same as '''pWindow->AddPendingEvent(event)'''. Either will put the event in the ''event queue'' of the wxEvtHandler object, meaning that the event will not be processed immediately. They can therefore be used to communicate safely between a worker thread and the main gui thread. The delay can also be useful if you want something to happen, but not until an event already in the event queue has been processed.
+
<tt>wxPostEvent</tt> is just a wrapper for wxEvtHandler::AddPendingEvent: '''wxPostEvent(pWindow,event)''' is the same as '''pWindow->GetEventHandler()->AddPendingEvent(event)'''. Either will put the event in the ''event queue'' of the wxEvtHandler object, meaning that the event will not be processed immediately. They can therefore be used to communicate safely between a worker thread and the main gui thread. The delay can also be useful if you want something to happen, but not until an event already in the event queue has been processed.
  
 
Note that the event queue can be flushed by calling wxApp::Yield or one of its variants (e.g. wxYieldIfNeeded()).
 
Note that the event queue can be flushed by calling wxApp::Yield or one of its variants (e.g. wxYieldIfNeeded()).
Line 77: Line 76:
 
For example, the event table entry to catch plain wxCommandEvents has a definition (in wx/event.h) that starts:
 
For example, the event table entry to catch plain wxCommandEvents has a definition (in wx/event.h) that starts:
  
<source>#define EVT_COMMAND(winid, event, func)</source>
+
<syntaxhighlight lang="cpp">#define EVT_COMMAND(winid, event, func)</syntaxhighlight>
  
 
But what is 'event'? It's a wxEventType. So you can't have an entry like this where wxCommandEvent is a class, not an int:
 
But what is 'event'? It's a wxEventType. So you can't have an entry like this where wxCommandEvent is a class, not an int:
  
<source>EVT_COMMAND(wxID_ANY, wxCommandEvent, myClass::Foo)</source>
+
<syntaxhighlight lang="cpp">EVT_COMMAND(wxID_ANY, wxCommandEvent, myClass::Foo)</syntaxhighlight>
  
 
You have to either [[#The simplest case|reuse an existing wxEventType]], or [[#The Normal Case|create one of your own]].
 
You have to either [[#The simplest case|reuse an existing wxEventType]], or [[#The Normal Case|create one of your own]].
Line 88: Line 87:
  
 
Example of custom event creation managing a click (by Marco Cavallini)
 
Example of custom event creation managing a click (by Marco Cavallini)
<source title="Header File">
+
<syntaxhighlight lang="cpp" title="Header File">
const wxEventType newEVT_MYCLASS_CLICK = wxNewEventType();
+
extern const wxEventType newEVT_MYCLASS_CLICK;
  
 
#define EVT_MYCLASS_CLICK(id, fn)                                \
 
#define EVT_MYCLASS_CLICK(id, fn)                                \
Line 95: Line 94:
 
(wxObjectEventFunction) (wxEventFunction)                \
 
(wxObjectEventFunction) (wxEventFunction)                \
 
(wxCommandEventFunction) & fn, (wxObject*) NULL ),
 
(wxCommandEventFunction) & fn, (wxObject*) NULL ),
</source>
+
</syntaxhighlight>
  
 
In the class you have to manage the event as you like and send your custom one to the event table:
 
In the class you have to manage the event as you like and send your custom one to the event table:
<source title="Source File">
+
<syntaxhighlight lang="cpp" title="Source File">
 +
const wxEventType newEVT_MYCLASS_CLICK = wxNewEventType();
 +
 
 
void Myclass::OnMouse( wxMouseEvent & event )
 
void Myclass::OnMouse( wxMouseEvent & event )
 
{
 
{
Line 108: Line 109:
 
   }
 
   }
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
== Creating a Custom Event - Method 2 ==
 
== Creating a Custom Event - Method 2 ==
Line 116: Line 117:
 
First, the declaration (needed to scope the event) and then the definition:
 
First, the declaration (needed to scope the event) and then the definition:
  
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_DECLARE_EVENT_TYPES()
 
BEGIN_DECLARE_EVENT_TYPES()
 
DECLARE_LOCAL_EVENT_TYPE( myEVT_SOMETHINGHAPPENED, wxNewEventType() )
 
DECLARE_LOCAL_EVENT_TYPE( myEVT_SOMETHINGHAPPENED, wxNewEventType() )
Line 122: Line 123:
  
 
DEFINE_LOCAL_EVENT_TYPE( myEVT_SOMETHINGHAPPENED )
 
DEFINE_LOCAL_EVENT_TYPE( myEVT_SOMETHINGHAPPENED )
</source>
+
</syntaxhighlight>
  
 
The event type isn't used by the macro. 7777 appears to be an ad-hoc standard: any value works but unique is "better". My spurious wxNewEventType() argument is almost certainly ''incorrect'' because it's in the declaration not the definition. In my code the declaration is only hit once, so that's okay.
 
The event type isn't used by the macro. 7777 appears to be an ad-hoc standard: any value works but unique is "better". My spurious wxNewEventType() argument is almost certainly ''incorrect'' because it's in the declaration not the definition. In my code the declaration is only hit once, so that's okay.
Line 128: Line 129:
 
Then in your event table (in this case, based on a wxControl):
 
Then in your event table (in this case, based on a wxControl):
  
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_EVENT_TABLE( myFunkyObject, wxControl )
 
BEGIN_EVENT_TABLE( myFunkyObject, wxControl )
 
   EVT_CUSTOM( myEVT_SOMETHINGHAPPENED, wxID_ANY, myFunkyObject::OnSomethingHappened )
 
   EVT_CUSTOM( myEVT_SOMETHINGHAPPENED, wxID_ANY, myFunkyObject::OnSomethingHappened )
Line 137: Line 138:
 
...
 
...
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
I'm not sure what the id field in EVT_CUSTOM is for (it's the starting id number) but -1 (wxID_ANY) seems to work fine.
 
I'm not sure what the id field in EVT_CUSTOM is for (it's the starting id number) but -1 (wxID_ANY) seems to work fine.
Line 143: Line 144:
 
Then, to make something happen with your event from another object, do this:
 
Then, to make something happen with your event from another object, do this:
  
<source>
+
<syntaxhighlight lang="cpp">
 
myDifferentObject::makesomethinghappen(int what)
 
myDifferentObject::makesomethinghappen(int what)
 
{
 
{
Line 150: Line 151:
 
   wxPostEvent( ptr_to_a_myFunkyObject_chain, event );
 
   wxPostEvent( ptr_to_a_myFunkyObject_chain, event );
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
(D.F. Smith, Aug 2004)
 
(D.F. Smith, Aug 2004)
Line 158: Line 159:
 
You need to declare your event type first:
 
You need to declare your event type first:
  
<source>
+
<syntaxhighlight lang="cpp">
 
DECLARE_EVENT_TYPE(wxCUSTOM_EVENT, 7777)
 
DECLARE_EVENT_TYPE(wxCUSTOM_EVENT, 7777)
 
DEFINE_EVENT_TYPE(wxCUSTOM_EVENT)
 
DEFINE_EVENT_TYPE(wxCUSTOM_EVENT)
</source>
+
</syntaxhighlight>
  
 
The second argument to DECLARE_EVENT_TYPE is only needed in wxWidgets < 2.4.0, and it's your event id there which must be unique. As of 2.4.0, event ID's are dynamically allocated at runtime so theres no conflicts.
 
The second argument to DECLARE_EVENT_TYPE is only needed in wxWidgets < 2.4.0, and it's your event id there which must be unique. As of 2.4.0, event ID's are dynamically allocated at runtime so theres no conflicts.
  
 
Next, you'll want an event table macro for your event. This one can be pretty funky:
 
Next, you'll want an event table macro for your event. This one can be pretty funky:
<source>
+
<syntaxhighlight lang="cpp">
 
#define EVT_CUSTOM_EVENT(fn)                                            \
 
#define EVT_CUSTOM_EVENT(fn)                                            \
 
DECLARE_EVENT_TABLE_ENTRY( wxCUSTOM_EVENT, wxID_ANY, wxID_ANY,  \\
 
DECLARE_EVENT_TABLE_ENTRY( wxCUSTOM_EVENT, wxID_ANY, wxID_ANY,  \\
 
(wxObjectEventFunction)(wxEventFunction)&fn, (wxObject*) NULL ),
 
(wxObjectEventFunction)(wxEventFunction)&fn, (wxObject*) NULL ),
</source>
+
</syntaxhighlight>
  
 
This is a declaration that doesn't want an ID, and it's for wxEvent-derived events. You'll need to add a cast to wxCommandEvent for command events, and add arguments for events that have IDs.
 
This is a declaration that doesn't want an ID, and it's for wxEvent-derived events. You'll need to add a cast to wxCommandEvent for command events, and add arguments for events that have IDs.
Line 179: Line 180:
 
* Set the m_eventType param with your new event type in the constructor.
 
* Set the m_eventType param with your new event type in the constructor.
 
* Implement a virtual Clone() method:
 
* Implement a virtual Clone() method:
<source>virtual wxEvent *Clone() const { return new wxCustomEvent(*this); }</source>
+
<syntaxhighlight lang="cpp">virtual wxEvent *Clone() const { return new wxCustomEvent(*this); }</syntaxhighlight>
 
* Implement a copy constructor.
 
* Implement a copy constructor.
 
* Be sure to use the DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros.
 
* Be sure to use the DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros.
Line 185: Line 186:
 
A quick custom event example:
 
A quick custom event example:
  
<source title="customevent.h">
+
<syntaxhighlight lang="cpp" title="customevent.h">
 
DECLARE_EVENT_TYPE(wxCUSTOM_EVENT, 7777)
 
DECLARE_EVENT_TYPE(wxCUSTOM_EVENT, 7777)
  
Line 203: Line 204:
 
DECLARE_DYNAMIC_CLASS(wxCustomEvent)
 
DECLARE_DYNAMIC_CLASS(wxCustomEvent)
 
};
 
};
</source>
+
</syntaxhighlight>
  
<source title="customevent.cpp">
+
<syntaxhighlight lang="cpp" title="customevent.cpp">
 
DEFINE_EVENT_TYPE( wxCUSTOM_EVENT );
 
DEFINE_EVENT_TYPE( wxCUSTOM_EVENT );
 
IMPLEMENT_DYNAMIC_CLASS( wxCustomEvent, wxEvent )
 
IMPLEMENT_DYNAMIC_CLASS( wxCustomEvent, wxEvent )
Line 216: Line 217:
 
this->m_eventType = event.m_eventType;
 
this->m_eventType = event.m_eventType;
 
}
 
}
</source>
+
</syntaxhighlight>
  
 
Using your new class:
 
Using your new class:
  
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_EVENT_TABLE( myFrame, wxFrame )
 
BEGIN_EVENT_TABLE( myFrame, wxFrame )
 
   EVT_CUSTOM_EVENT( myFrame::HandleCustomEvent )
 
   EVT_CUSTOM_EVENT( myFrame::HandleCustomEvent )
 
END_EVENT_TABLE()
 
END_EVENT_TABLE()
</source>
+
</syntaxhighlight>
  
 
== Creating a Custom Event - Method 4 ==
 
== Creating a Custom Event - Method 4 ==
Line 230: Line 231:
 
This shows how to create a custom event class, which carries a trivial amount of data, and the alternative ways to make it work.
 
This shows how to create a custom event class, which carries a trivial amount of data, and the alternative ways to make it work.
  
<source title="Header File">
+
<syntaxhighlight lang="cpp" title="Header File">
 
// Could have been DECLARE_EVENT_TYPE( MyFooCommandEvent, -1 )
 
// Could have been DECLARE_EVENT_TYPE( MyFooCommandEvent, -1 )
 
// Not needed if you only use the event-type in one .cpp file
 
// Not needed if you only use the event-type in one .cpp file
 
extern expdecl const wxEventType MyFooCommandEvent;
 
extern expdecl const wxEventType MyFooCommandEvent;
  
// An custom event that transports a whole wxString.
+
// A custom event that transports a whole wxString.
 
class MyFooEvent: public wxCommandEvent
 
class MyFooEvent: public wxCommandEvent
 
{
 
{
Line 260: Line 261:
 
// This #define simplifies the one below, and makes the syntax less
 
// This #define simplifies the one below, and makes the syntax less
 
// ugly if you want to use Connect() instead of an event table.
 
// ugly if you want to use Connect() instead of an event table.
#define MyFooEventHandler(func)                                           \
+
#define MyFooEventHandler(func)                                         \
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) \
+
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)\\
wxStaticCastEvent(MyFooEventFunction, &func)
+
wxStaticCastEvent(MyFooEventFunction, &func)                  
  
 
// Define the event table entry. Yes, it really *does* end in a comma.
 
// Define the event table entry. Yes, it really *does* end in a comma.
 
#define EVT_MYFOO(id, fn)                                            \
 
#define EVT_MYFOO(id, fn)                                            \
DECLARE_EVENT_TABLE_ENTRY( MyFooCommandEvent, id, wxID_ANY,  \
+
DECLARE_EVENT_TABLE_ENTRY( MyFooCommandEvent, id, wxID_ANY,  \\
(wxObjectEventFunction)(wxEventFunction)                    \
+
(wxObjectEventFunction)(wxEventFunction)                    \\
(wxCommandEventFunction) wxStaticCastEvent(                  \
+
(wxCommandEventFunction) wxStaticCastEvent(                  \\
 
MyFooEventFunction, &fn ), (wxObject*) NULL ),
 
MyFooEventFunction, &fn ), (wxObject*) NULL ),
  
 
// Optionally, you can do a similar #define for EVT_MYFOO_RANGE.
 
// Optionally, you can do a similar #define for EVT_MYFOO_RANGE.
 
#define EVT_MYFOO_RANGE(id1,id2, fn)                                \
 
#define EVT_MYFOO_RANGE(id1,id2, fn)                                \
DECLARE_EVENT_TABLE_ENTRY( MyFooCommandEvent, id1, id2,      \
+
DECLARE_EVENT_TABLE_ENTRY( MyFooCommandEvent, id1, id2,      \\
 
MyFooEventHandler(fn), (wxObject*) NULL ),
 
MyFooEventHandler(fn), (wxObject*) NULL ),
  
Line 280: Line 281:
 
// named IDs in an enumeration.
 
// named IDs in an enumeration.
 
enum { Foo_DoFirstThing = 1, Foo_DoSecondThing, Foo_DoThirdThing };
 
enum { Foo_DoFirstThing = 1, Foo_DoSecondThing, Foo_DoThirdThing };
</source>
+
</syntaxhighlight>
  
<source title="Source File">
+
<syntaxhighlight lang="cpp" title="Source File">
 
// Could have been DEFINE_EVENT_TYPE( MyFooCommandEvent )
 
// Could have been DEFINE_EVENT_TYPE( MyFooCommandEvent )
 
const wxEventType MyFooCommandEvent = wxNewEventType();
 
const wxEventType MyFooCommandEvent = wxNewEventType();
Line 310: Line 311:
  
 
// Or use Connect(). You'd probably do this in the MyDestination constructor.
 
// Or use Connect(). You'd probably do this in the MyDestination constructor.
Connect( wxID_ANY, MyFooCommandEvent,
+
Connect(wxID_ANY, MyFooCommandEvent,
MyFooEventHandler(MyDestination::DoSomething), NULL, this );
+
MyFooEventHandler(MyDestination::DoSomething), NULL, this);
 +
 
 +
// Or, if you use >=wx2.9, Bind(). Again probably in the MyDestination constructor, do:
 +
Bind(MyFooCommandEvent, MyFooEventHandler(MyDestination::DoSomething), this, wxID_ANY);
 +
 
  
 
// To handle the event:
 
// To handle the event:
Line 326: Line 331:
 
}
 
}
 
}
 
}
</source>
+
</syntaxhighlight>
 +
 
 +
=== A Multiple Inheritance Gotcha: ===
 +
 
 +
If you use multiple inheritance, and inherit from both a wxWidgets event class
 +
(like wxCommandEvent) and a custom mixin class of your own, the wxWidgets event
 +
class MUST appear first in the list of parent classes. For example:
 +
<pre>
 +
  class MyFooEvent: public wxCommandEvent, public MyEventMixinClass ...
 +
</pre>
 +
If you don't put the wxWidgets class first, references to the class will not be
 +
handled properly. An indicator of this is when invoking wxEvent methods on
 +
an instance of your derived event type, an assertion dialog appears
 +
with a message like:
 +
 
 +
<pre>
 +
/...wxWidgetsInstallPath.../wxGTK-2.8.11/src/common/object.cpp(378):
 +
assert "wxAssertFailure" failed in CreateRefData():
 +
CreateRefData() must be overridden if called!
 +
</pre>
 +
 
 +
It should not be necessary to override CreateRefData(). Just check that
 +
your are specifying your parent event types in the right order.
  
 
== The EVT_CUSTOM Macro Method ==
 
== The EVT_CUSTOM Macro Method ==
Line 332: Line 359:
 
A different approach is to use the EVT_CUSTOM macro. This has the distinct advantage that you don't need the other, complicated macro stuff. Just make your new event type (and declare it too if necessary):
 
A different approach is to use the EVT_CUSTOM macro. This has the distinct advantage that you don't need the other, complicated macro stuff. Just make your new event type (and declare it too if necessary):
  
<source>const wxEventType MyFooCommandEvent = wxNewEventType();</source>
+
<syntaxhighlight lang="cpp">const wxEventType MyFooCommandEvent = wxNewEventType();</syntaxhighlight>
  
 
Then create your MyFooEvent class. All you need to do from there is use EVT_CUSTOM directly in the event table:
 
Then create your MyFooEvent class. All you need to do from there is use EVT_CUSTOM directly in the event table:
  
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_EVENT_TABLE( MyDestination,wxDestination )
 
BEGIN_EVENT_TABLE( MyDestination,wxDestination )
 
EVT_CUSTOM( MyFooCommandEvent, wxID_ANY, MyDestination::DoSomething )
 
EVT_CUSTOM( MyFooCommandEvent, wxID_ANY, MyDestination::DoSomething )
 
END_EVENT_TABLE()
 
END_EVENT_TABLE()
</source>
+
</syntaxhighlight>
  
 
Then send and receive as before.
 
Then send and receive as before.
Line 346: Line 373:
 
Much simpler, so why not do it all the time? Well, I don't think you can do this with Connect(). More importantly, the macro expects MyDestination::DoSomething to take a wxEvent& parameter, not a wxFooEvent&, so you'd have to change the function to:
 
Much simpler, so why not do it all the time? Well, I don't think you can do this with Connect(). More importantly, the macro expects MyDestination::DoSomething to take a wxEvent& parameter, not a wxFooEvent&, so you'd have to change the function to:
  
<source>void MyDestination::DoSomething( wxEvent& event )</source>
+
<syntaxhighlight lang="cpp">void MyDestination::DoSomething( wxEvent& event )</syntaxhighlight>
  
 
This means that whenever you want to access the data in the event, you would need to cast. So the switch statement would need to be:
 
This means that whenever you want to access the data in the event, you would need to cast. So the switch statement would need to be:
  
<source>case Foo_DoFirstThing: wxLogDebug( ((MyFooEvent&)event).GetText() ); break;</source>
+
<syntaxhighlight lang="cpp">case Foo_DoFirstThing: wxLogDebug( ((MyFooEvent&)event).GetText() ); break;</syntaxhighlight>
  
 
== "But I don't need a whole new event class..." ==
 
== "But I don't need a whole new event class..." ==
Line 358: Line 385:
 
=== The simplest case ===
 
=== The simplest case ===
  
The event must have an eventtype. The simplest way is to reuse a pre-existing one e.g. wxEVT_COMMAND_BUTTON_CLICKED. In the originating function, create your event:
+
The event must have an eventtype. The simplest way is to reuse [[Lists of wxEventTypes|a pre-existing one]] e.g. wxEVT_COMMAND_BUTTON_CLICKED. In the originating function, create your event:
  
<source>
+
<syntaxhighlight lang="cpp">
 
wxCommandEvent MyEvent( wxEVT_COMMAND_BUTTON_CLICKED ); // Keep it simple, don't give a specific event ID
 
wxCommandEvent MyEvent( wxEVT_COMMAND_BUTTON_CLICKED ); // Keep it simple, don't give a specific event ID
//wxPostEvent(this, MyEvent); // This posts to ourselves: it'll be caught and sent to a different method
+
wxPostEvent(this, MyEvent); // This posts to ourselves: it'll be caught and sent to a different method
 
wxPostEvent(pBar, MyEvent); // Posts to a different class, Bar, where pBar points to an instance of Bar
 
wxPostEvent(pBar, MyEvent); // Posts to a different class, Bar, where pBar points to an instance of Bar
</source>
+
</syntaxhighlight>
  
 
The event table would be:
 
The event table would be:
  
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_EVENT_TABLE(MyFoo, wxSomething)
 
BEGIN_EVENT_TABLE(MyFoo, wxSomething)
 
   EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, MyFoo::OnMyEvent)
 
   EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, MyFoo::OnMyEvent)
 
   ...
 
   ...
 
END_EVENT_TABLE()
 
END_EVENT_TABLE()
</source>
+
</syntaxhighlight>
  
 
and the handler's signature would be '''void MyFoo::OnMyEvent(wxCommandEvent&)'''
 
and the handler's signature would be '''void MyFoo::OnMyEvent(wxCommandEvent&)'''
Line 381: Line 408:
 
The simplest case method works. However reusing wxEVT_COMMAND_BUTTON_CLICKED would look rather confusing, and there's a (small) chance of the event being caught by the wrong event table entry. A better way is to create a unique eventtype, and send this instead.
 
The simplest case method works. However reusing wxEVT_COMMAND_BUTTON_CLICKED would look rather confusing, and there's a (small) chance of the event being caught by the wrong event table entry. A better way is to create a unique eventtype, and send this instead.
  
<source>
+
<syntaxhighlight lang="cpp">
 
// This goes somewhere in a cpp file, before you use it (unless you've declared it elsewhere)
 
// This goes somewhere in a cpp file, before you use it (unless you've declared it elsewhere)
 
const wxEventType MyExcitingEvent = wxNewEventType(); // You get to choose the name yourself
 
const wxEventType MyExcitingEvent = wxNewEventType(); // You get to choose the name yourself
Line 390: Line 417:
 
wxPostEvent(this, MyEvent); // This posts to ourselves: it'll be caught and sent to a different method
 
wxPostEvent(this, MyEvent); // This posts to ourselves: it'll be caught and sent to a different method
 
wxPostEvent(pBar, MyEvent); // Posts to a different class, Bar, where pBar points to an instance of Bar
 
wxPostEvent(pBar, MyEvent); // Posts to a different class, Bar, where pBar points to an instance of Bar
</source>
+
</syntaxhighlight>
 
The event table would be:
 
The event table would be:
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_EVENT_TABLE(MyFoo, wxSomething)
 
BEGIN_EVENT_TABLE(MyFoo, wxSomething)
 
   EVT_COMMAND(wxID_ANY, MyExcitingEvent, MyFoo::OnMyEvent)
 
   EVT_COMMAND(wxID_ANY, MyExcitingEvent, MyFoo::OnMyEvent)
 
   ...
 
   ...
 
END_EVENT_TABLE()
 
END_EVENT_TABLE()
</source>
+
</syntaxhighlight>
  
 
The handler's signature is still '''void MyFoo::OnMyEvent(wxCommandEvent&)'''
 
The handler's signature is still '''void MyFoo::OnMyEvent(wxCommandEvent&)'''
Line 403: Line 430:
 
Most of the time all of this will be happening within the same cpp file. However if you need to use your eventtype elsewhere, you'll need to declare it there as an extern:
 
Most of the time all of this will be happening within the same cpp file. However if you need to use your eventtype elsewhere, you'll need to declare it there as an extern:
  
<source>extern const wxEventType MyExcitingEvent;</source>
+
<syntaxhighlight lang="cpp">extern const wxEventType MyExcitingEvent;</syntaxhighlight>
  
 
=== The individual ID case ===
 
=== The individual ID case ===
Line 409: Line 436:
 
What if you want to send several messages? Well, you ''could'' create several eventtypes: they're only ints after all, there isn't a world shortage. But it's a bit easier to have just one eventtype, and use different IDs for different destinations. It's easier to read if you do that with an enum.
 
What if you want to send several messages? Well, you ''could'' create several eventtypes: they're only ints after all, there isn't a world shortage. But it's a bit easier to have just one eventtype, and use different IDs for different destinations. It's easier to read if you do that with an enum.
  
<source>
+
<syntaxhighlight lang="cpp">
 
// The values don't matter, as they're only used with this eventtype
 
// The values don't matter, as they're only used with this eventtype
 
enum { Foo_DoFirstThing = 1, Foo_DoSecondThing, Foo_DoThirdThing };
 
enum { Foo_DoFirstThing = 1, Foo_DoSecondThing, Foo_DoThirdThing };
Line 417: Line 444:
 
// The first two events are posted to ourselves
 
// The first two events are posted to ourselves
 
wxCommandEvent MyEvent1( MyExcitingEvent, Foo_DoFirstThing ); wxPostEvent(this, MyEvent1);
 
wxCommandEvent MyEvent1( MyExcitingEvent, Foo_DoFirstThing ); wxPostEvent(this, MyEvent1);
wxCommandEvent MyEvent2( MyExcitingEvent, Foo_DoSecondThing, ); wxPostEvent(this, MyEvent2);
+
wxCommandEvent MyEvent2( MyExcitingEvent, Foo_DoSecondThing ); wxPostEvent(this, MyEvent2);
 
// Just for variety, let's send the third one elsewhere:
 
// Just for variety, let's send the third one elsewhere:
 
wxCommandEvent MyEvent3( MyExcitingEvent, Foo_DoThirdThing ); wxPostEvent(pBar, MyEvent3);
 
wxCommandEvent MyEvent3( MyExcitingEvent, Foo_DoThirdThing ); wxPostEvent(pBar, MyEvent3);
</source>
+
</syntaxhighlight>
  
 
The MyFoo event table would be:
 
The MyFoo event table would be:
  
<source>
+
<syntaxhighlight lang="cpp">
 
BEGIN_EVENT_TABLE(MyFoo, wxSomething)
 
BEGIN_EVENT_TABLE(MyFoo, wxSomething)
 
   EVT_COMMAND(Foo_DoFirstThing, MyExcitingEvent, MyFoo::OnMyFirstEvent)
 
   EVT_COMMAND(Foo_DoFirstThing, MyExcitingEvent, MyFoo::OnMyFirstEvent)
   EVT_COMMAND(Foo_DoSecondThing,, MyExcitingEvent, MyFoo::OnMySecondEvent)
+
   EVT_COMMAND(Foo_DoSecondThing, MyExcitingEvent, MyFoo::OnMySecondEvent)
 
   ...
 
   ...
 
END_EVENT_TABLE()
 
END_EVENT_TABLE()
</source>
+
</syntaxhighlight>
  
 
Alternatively you could catch everything as before with wxID_ANY, and discriminate between them in the handler with event.GetId().
 
Alternatively you could catch everything as before with wxID_ANY, and discriminate between them in the handler with event.GetId().

Latest revision as of 19:36, 19 October 2018

The information here is provided to supplement the Custom Event Summary which you should read first. Also, it is a good idea to look at the events project in the distribution samples directory.

You may also find the following articles helpful:

Quick User Notes

  • EVT_FOO(-1, SomeClass::SomeFunc) is a purely passive declaration. It says, "If a FOO happens to come my way, let me know about it." It doesn't tell any particular FOO-generating class to notify this class about FOO events. But without this, it will not respond to FOO events at all, even if explicitly sent to an object of this class.
  • wxButton events seem to work automatically because the EVT_BUTTON is generated in the wxButton itself, and since it's a command event it propagates to its parents automatically. Thus, no call to SetEventHandler() or similar is necessary.
  • wxSocket events do not exist in a chain of parents, so SetEventHandler() is necessary. This establishes the connection between an event and a particular instance of an object.
  • Note that there are other strategies for the event dispatching as well, except the first two mentioned above:
    • Send the event to oneself (possibly relying on it to be propagated to the parent).
    • Send the event to another event handler explicitly associated with us.
    • Send the event to all top level windows (possibly relying on them to propagate the event *downwards* to their children recursively; example: EVT_IDLE) NB. downward propagation of wx events only happens for idle events.
    • Send the event to wxTheApp only.
  • In sub-classing wxEvent, remember to associate your event (wxFooEvent) to your event type (wxEVT_FOO) in the constructor:
wxFooEvent( int id = 0 )
: wxEvent (id, wxEVT_FOO)
{
...
}
  • To get a unique wxEVT_FOO, use:
wxEVT_FOO = wxNewEventType();

wxEvtHandler::ProcessEvent vs. wxPostEvent and wxEvtHandler::AddPendingEvent

These can be used when the event handler object (usually a wxWindow) is known at compile time.

wxEvtHandler::ProcessEvent(wxEvent &event)

ProcessEvent will call the event handler directly and the event will be processed immediately, like a function call.

wxEvtHandler::AddPendingEvent(wxEvent& event)
wxPostEvent(wxEvtHandler *evtHandler, wxEvent &event)

wxPostEvent is just a wrapper for wxEvtHandler::AddPendingEvent: wxPostEvent(pWindow,event) is the same as pWindow->GetEventHandler()->AddPendingEvent(event). Either will put the event in the event queue of the wxEvtHandler object, meaning that the event will not be processed immediately. They can therefore be used to communicate safely between a worker thread and the main gui thread. The delay can also be useful if you want something to happen, but not until an event already in the event queue has been processed.

Note that the event queue can be flushed by calling wxApp::Yield or one of its variants (e.g. wxYieldIfNeeded()).

Why are Custom Events So Confusing?

An Explanation of the Macros

Part of the problem is that some examples use macros, and some don't. So there seem to be several different ways to do something, when in fact they are identical. Here is a list of the important equivalents.

  • DECLARE_EVENT_TYPE( MyFooCommandEvent, wxID_ANY )
is the same as
extern expdecl const wxEventType MyFooCommandEvent;
  • DEFINE_EVENT_TYPE( MyFooCommandEvent )
is the same as
const wxEventType MyFooCommandEvent = wxNewEventType();
  • BEGIN_DECLARE_EVENT_TYPES() and END_DECLARE_EVENT_TYPES()
used to do something. Starting from wxWidgets 2.4 they are empty!

It's not a macro, but since wxWidgets 2.4

  • wxNewEventType()
is used instead of doing things like
const newEVT_MYCLASS_FIRST = wxEVT_FIRST + 5400;

There is also EVT_CUSTOM (and EVT_CUSTOM_RANGE). More about this below, but for the record

  • EVT_CUSTOM(eventtype, id, func)
becomes wx__DECLARE_EVT1(eventtype, id, wxEventHandler(func))
which becomes
DECLARE_EVENT_TABLE_ENTRY(eventtype, id, wxID_ANY, func, NULL),

Events and wxEventType

An event is an object of class wxEvent, or more usually of one of its derivatives. A wxEventType is just an int, with a unique value. However the (understandable) tendency to use names like MyFooCommandEvent for eventtypes means that there is scope for confusion.

For example, the event table entry to catch plain wxCommandEvents has a definition (in wx/event.h) that starts:

#define EVT_COMMAND(winid, event, func)

But what is 'event'? It's a wxEventType. So you can't have an entry like this where wxCommandEvent is a class, not an int:

EVT_COMMAND(wxID_ANY, wxCommandEvent, myClass::Foo)

You have to either reuse an existing wxEventType, or create one of your own.

Creating a Custom Event - Method 1

Example of custom event creation managing a click (by Marco Cavallini)

extern const wxEventType newEVT_MYCLASS_CLICK;

#define EVT_MYCLASS_CLICK(id, fn)                                 \
	DECLARE_EVENT_TABLE_ENTRY( newEVT_MYCLASS_CLICK, id, -1,  \
	(wxObjectEventFunction) (wxEventFunction)                 \
	(wxCommandEventFunction) & fn, (wxObject*) NULL ),

In the class you have to manage the event as you like and send your custom one to the event table:

const wxEventType newEVT_MYCLASS_CLICK = wxNewEventType();

void Myclass::OnMouse( wxMouseEvent & event )
{
   if ( event.LeftIsDown() )
   {
   wxCommandEvent event( newEVT_MYCLASS_CLICK, GetId() );
   event.SetEventObject(this);
   ProcessCommand(event);
   }
}

Creating a Custom Event - Method 2

This was tested under wxWidgets 2.4.2 (GTK) and seems to be less complicated than the other methods here. It was derived from the event.cpp example, and uses a wxCommandEvent to pass data.

First, the declaration (needed to scope the event) and then the definition:

BEGIN_DECLARE_EVENT_TYPES()
	DECLARE_LOCAL_EVENT_TYPE( myEVT_SOMETHINGHAPPENED, wxNewEventType() )
END_DECLARE_EVENT_TYPES()

DEFINE_LOCAL_EVENT_TYPE( myEVT_SOMETHINGHAPPENED )

The event type isn't used by the macro. 7777 appears to be an ad-hoc standard: any value works but unique is "better". My spurious wxNewEventType() argument is almost certainly incorrect because it's in the declaration not the definition. In my code the declaration is only hit once, so that's okay.

Then in your event table (in this case, based on a wxControl):

BEGIN_EVENT_TABLE( myFunkyObject, wxControl )
   EVT_CUSTOM( myEVT_SOMETHINGHAPPENED, wxID_ANY, myFunkyObject::OnSomethingHappened )
END_EVENT_TABLE()

myFunkyObject::OnSomethingHappened( wxCommandEvent &event )
{
...
}

I'm not sure what the id field in EVT_CUSTOM is for (it's the starting id number) but -1 (wxID_ANY) seems to work fine.

Then, to make something happen with your event from another object, do this:

myDifferentObject::makesomethinghappen(int what)
{
   wxCommandEvent event( myEVT_SOMETHINGHAPPENED );
   event.SetInt(what);
   wxPostEvent( ptr_to_a_myFunkyObject_chain, event );
}

(D.F. Smith, Aug 2004)

Creating a Custom Event - Method 3

You need to declare your event type first:

DECLARE_EVENT_TYPE(wxCUSTOM_EVENT, 7777)
DEFINE_EVENT_TYPE(wxCUSTOM_EVENT)

The second argument to DECLARE_EVENT_TYPE is only needed in wxWidgets < 2.4.0, and it's your event id there which must be unique. As of 2.4.0, event ID's are dynamically allocated at runtime so theres no conflicts.

Next, you'll want an event table macro for your event. This one can be pretty funky:

#define EVT_CUSTOM_EVENT(fn)                                             \
	DECLARE_EVENT_TABLE_ENTRY( wxCUSTOM_EVENT, wxID_ANY, wxID_ANY,   \\
	(wxObjectEventFunction)(wxEventFunction)&fn, (wxObject*) NULL ),

This is a declaration that doesn't want an ID, and it's for wxEvent-derived events. You'll need to add a cast to wxCommandEvent for command events, and add arguments for events that have IDs.

TODO: provide an example

Finally, implement your event itself. The things to remember are:

  • Set the m_eventType param with your new event type in the constructor.
  • Implement a virtual Clone() method:
virtual wxEvent *Clone() const { return new wxCustomEvent(*this); }
  • Implement a copy constructor.
  • Be sure to use the DECLARE_DYNAMIC_CLASS and IMPLEMENT_DYNAMIC_CLASS macros.

A quick custom event example:

DECLARE_EVENT_TYPE(wxCUSTOM_EVENT, 7777)

#define EVT_CUSTOM_EVENT(fn)                                             \
	DECLARE_EVENT_TABLE_ENTRY( wxCUSTOM_EVENT, wxID_ANY, wxID_ANY,   \\
	(wxObjectEventFunction)(wxEventFunction)&fn, (wxObject*) NULL ),

class wxCustomEvent : public wxEvent
{
public:
	wxCustomEvent();
	wxCustomEvent( const wxCustomEvent &event );

	virtual wxEvent *Clone() const
		{ return new wxCustomEvent(*this); };

	DECLARE_DYNAMIC_CLASS(wxCustomEvent)
};
DEFINE_EVENT_TYPE( wxCUSTOM_EVENT );
IMPLEMENT_DYNAMIC_CLASS( wxCustomEvent, wxEvent )

wxCustomEvent::wxCustomEvent() : m_eventType(wxCUSTOM_EVENT) { }

wxCustomEvent::wxCustomEvent( const wxCustomEvent &event )
{
	// not really needed in this sample, but it's boring to have it empty
	this->m_eventType = event.m_eventType;
}

Using your new class:

BEGIN_EVENT_TABLE( myFrame, wxFrame )
   EVT_CUSTOM_EVENT( myFrame::HandleCustomEvent )
END_EVENT_TABLE()

Creating a Custom Event - Method 4

This shows how to create a custom event class, which carries a trivial amount of data, and the alternative ways to make it work.

// Could have been DECLARE_EVENT_TYPE( MyFooCommandEvent, -1 )
// Not needed if you only use the event-type in one .cpp file
extern expdecl const wxEventType MyFooCommandEvent;

// A custom event that transports a whole wxString.
class MyFooEvent: public wxCommandEvent
{
public:
	MyFooEvent( wxEventType commandType = MyFooCommandEvent, int id = 0 )
	:  wxCommandEvent(commandType, id) { }

	// You *must* copy here the data to be transported
	MyFooEvent( const MyFooEvent &event )
	:  wxCommandEvent(event) { this->SetText( event.GetText() ); }

	// Required for sending with wxPostEvent()
	wxEvent* Clone() const { return new MyFooEvent(*this); }

	wxString GetText() const { return m_Text; }
	void SetText( const wxString& text ) { m_Text = text; }

private:
	wxString m_Text;
};

typedef void (wxEvtHandler::*MyFooEventFunction)(MyFooEvent &);

// This #define simplifies the one below, and makes the syntax less
// ugly if you want to use Connect() instead of an event table.
#define MyFooEventHandler(func)                                         \
	(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)\\
	wxStaticCastEvent(MyFooEventFunction, &func)                    

// Define the event table entry. Yes, it really *does* end in a comma.
#define EVT_MYFOO(id, fn)                                            \
	DECLARE_EVENT_TABLE_ENTRY( MyFooCommandEvent, id, wxID_ANY,  \\
	(wxObjectEventFunction)(wxEventFunction)                     \\
	(wxCommandEventFunction) wxStaticCastEvent(                  \\
	MyFooEventFunction, &fn ), (wxObject*) NULL ),

// Optionally, you can do a similar #define for EVT_MYFOO_RANGE.
#define EVT_MYFOO_RANGE(id1,id2, fn)                                 \
	DECLARE_EVENT_TABLE_ENTRY( MyFooCommandEvent, id1, id2,      \\
	MyFooEventHandler(fn), (wxObject*) NULL ),

// If you want to use the custom event to send more than one sort
// of data, or to more than one place, make it easier by providing
// named IDs in an enumeration.
enum { Foo_DoFirstThing = 1, Foo_DoSecondThing, Foo_DoThirdThing };
// Could have been DEFINE_EVENT_TYPE( MyFooCommandEvent )
const wxEventType MyFooCommandEvent = wxNewEventType();

// Usage:

// To Send the Event

...
MyFooEvent event( MyFooCommandEvent, Foo_DoFirstThing );
wxString bar( wxT("This is a Foo_DoFirstThing event") );
// Add the exciting data. You can put anything you like
// into the class: ints, structs, binary data...
event.SetText( bar );
wxPostEvent( panel, event );
...

// To receive the event, either use an event table like so:

BEGIN_EVENT_TABLE( MyDestination, wxDestination )
      EVT_MYFOO( wxID_ANY, MyDestination::DoSomething )
// or EVT_MYFOO_RANGE( Foo_DoFirstThing, Foo_DoThirdThing, MyDestination::DoSomething )
// or EVT_MYFOO( Foo_DoFirstThing, MyDestination::DoFirstThing)
// or EVT_MYFOO( Foo_DoSecondThing, MyDestination::DoSecondThing)
// or EVT_MYFOO( Foo_DoThirdThing, MyDestination::DoThirdThing)
END_EVENT_TABLE()

// Or use Connect(). You'd probably do this in the MyDestination constructor.
Connect(wxID_ANY, MyFooCommandEvent,
	MyFooEventHandler(MyDestination::DoSomething), NULL, this);

// Or, if you use >=wx2.9, Bind(). Again probably in the MyDestination constructor, do:
Bind(MyFooCommandEvent,	MyFooEventHandler(MyDestination::DoSomething), this, wxID_ANY);


// To handle the event:

void MyDestination::DoSomething( MyFooEvent &event )
{
	switch( event.GetId() )
	{
	case Foo_DoFirstThing:
		wxLogDebug( event.GetText() ); break;
	case Foo_DoSecondThing:
		/* Do something different */ break;
	//  ...
	}
}

A Multiple Inheritance Gotcha:

If you use multiple inheritance, and inherit from both a wxWidgets event class (like wxCommandEvent) and a custom mixin class of your own, the wxWidgets event class MUST appear first in the list of parent classes. For example:

  class MyFooEvent: public wxCommandEvent, public MyEventMixinClass ...

If you don't put the wxWidgets class first, references to the class will not be handled properly. An indicator of this is when invoking wxEvent methods on an instance of your derived event type, an assertion dialog appears with a message like:

/...wxWidgetsInstallPath.../wxGTK-2.8.11/src/common/object.cpp(378):
assert "wxAssertFailure" failed in CreateRefData():
CreateRefData() must be overridden if called!

It should not be necessary to override CreateRefData(). Just check that your are specifying your parent event types in the right order.

The EVT_CUSTOM Macro Method

A different approach is to use the EVT_CUSTOM macro. This has the distinct advantage that you don't need the other, complicated macro stuff. Just make your new event type (and declare it too if necessary):

const wxEventType MyFooCommandEvent = wxNewEventType();

Then create your MyFooEvent class. All you need to do from there is use EVT_CUSTOM directly in the event table:

BEGIN_EVENT_TABLE( MyDestination,wxDestination )
	EVT_CUSTOM( MyFooCommandEvent, wxID_ANY, MyDestination::DoSomething )
END_EVENT_TABLE()

Then send and receive as before.

Much simpler, so why not do it all the time? Well, I don't think you can do this with Connect(). More importantly, the macro expects MyDestination::DoSomething to take a wxEvent& parameter, not a wxFooEvent&, so you'd have to change the function to:

void MyDestination::DoSomething( wxEvent& event )

This means that whenever you want to access the data in the event, you would need to cast. So the switch statement would need to be:

case Foo_DoFirstThing: wxLogDebug( ((MyFooEvent&)event).GetText() ); break;

"But I don't need a whole new event class..."

Often you'll want to send an event just to notify the receiving class that something has happened; in other words, you don't need to store data inside the event: the event itself is the message. So just send a wxCommandEvent with a specific type, and optionally a specific ID.

The simplest case

The event must have an eventtype. The simplest way is to reuse a pre-existing one e.g. wxEVT_COMMAND_BUTTON_CLICKED. In the originating function, create your event:

wxCommandEvent MyEvent( wxEVT_COMMAND_BUTTON_CLICKED ); // Keep it simple, don't give a specific event ID
wxPostEvent(this, MyEvent); // This posts to ourselves: it'll be caught and sent to a different method
wxPostEvent(pBar, MyEvent); // Posts to a different class, Bar, where pBar points to an instance of Bar

The event table would be:

BEGIN_EVENT_TABLE(MyFoo, wxSomething)
  EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, MyFoo::OnMyEvent)
  ...
END_EVENT_TABLE()

and the handler's signature would be void MyFoo::OnMyEvent(wxCommandEvent&)

The Normal Case

The simplest case method works. However reusing wxEVT_COMMAND_BUTTON_CLICKED would look rather confusing, and there's a (small) chance of the event being caught by the wrong event table entry. A better way is to create a unique eventtype, and send this instead.

// This goes somewhere in a cpp file, before you use it (unless you've declared it elsewhere)
const wxEventType MyExcitingEvent = wxNewEventType(); // You get to choose the name yourself

// In the posting method:
...
wxCommandEvent MyEvent( MyExcitingEvent ); // Still keeping it simple, don't give a specific event ID
wxPostEvent(this, MyEvent); // This posts to ourselves: it'll be caught and sent to a different method
wxPostEvent(pBar, MyEvent); // Posts to a different class, Bar, where pBar points to an instance of Bar

The event table would be:

BEGIN_EVENT_TABLE(MyFoo, wxSomething)
  EVT_COMMAND(wxID_ANY, MyExcitingEvent, MyFoo::OnMyEvent)
  ...
END_EVENT_TABLE()

The handler's signature is still void MyFoo::OnMyEvent(wxCommandEvent&)

Most of the time all of this will be happening within the same cpp file. However if you need to use your eventtype elsewhere, you'll need to declare it there as an extern:

extern const wxEventType MyExcitingEvent;

The individual ID case

What if you want to send several messages? Well, you could create several eventtypes: they're only ints after all, there isn't a world shortage. But it's a bit easier to have just one eventtype, and use different IDs for different destinations. It's easier to read if you do that with an enum.

// The values don't matter, as they're only used with this eventtype
enum { Foo_DoFirstThing = 1, Foo_DoSecondThing, Foo_DoThirdThing };

// In the posting method:
...
// The first two events are posted to ourselves
wxCommandEvent MyEvent1( MyExcitingEvent, Foo_DoFirstThing ); wxPostEvent(this, MyEvent1);
wxCommandEvent MyEvent2( MyExcitingEvent, Foo_DoSecondThing ); wxPostEvent(this, MyEvent2);
// Just for variety, let's send the third one elsewhere:
wxCommandEvent MyEvent3( MyExcitingEvent, Foo_DoThirdThing ); wxPostEvent(pBar, MyEvent3);

The MyFoo event table would be:

BEGIN_EVENT_TABLE(MyFoo, wxSomething)
  EVT_COMMAND(Foo_DoFirstThing, MyExcitingEvent, MyFoo::OnMyFirstEvent)
  EVT_COMMAND(Foo_DoSecondThing, MyExcitingEvent, MyFoo::OnMySecondEvent)
  ...
END_EVENT_TABLE()

Alternatively you could catch everything as before with wxID_ANY, and discriminate between them in the handler with event.GetId().