In the following code I do the following:
If I use the slightly old-fashioned wxEvtHandler::Connect method, (as I've commented out below), then everything works. But if I use the wxEvtHandler::Bind method I get a series of very cryptic error messages (posted after the code).
Since Bind allows more freedom and is easier to use (it doesn't require creating awkward macros), then I would like to use it instead of Connect ... any ideas?
Here's the code:
#include <wx/wx.h>
//Creating my own custom event which will hold a payload of some templated type
template <class Payload_type>
class TemplatedPayloadEvent : public wxCommandEvent
{
public:
TemplatedPayloadEvent(){}
TemplatedPayloadEvent(wxEventType eventType) : wxCommandEvent(eventType){}
TemplatedPayloadEvent(const TemplatedPayloadEvent& event)
: wxCommandEvent(event)
{
this->mPayload = event.mPayload;
}
virtual TemplatedPayloadEvent* Clone() const {return new TemplatedPayloadEvent(*this);}
void setPayload(Payload_type payload) {mPayload = payload;}
Payload_type getPayload() {return mPayload;}
private:
Payload_type mPayload;
};
//instantiating new event along with associated elements
class wxStringPayloadEvent : public TemplatedPayloadEvent<wxString>
{
public:
wxStringPayloadEvent() : TemplatedPayloadEvent<wxString>(wxEVT_STRING_PAYLOAD){};
};
typedef void (wxEvtHandler::*wxStringPayloadEventFunction)(wxStringPayloadEvent&);
#define wxStringPayloadEventHandler(func) \
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction)\
wxStaticCastEvent(wxStringPayloadEventFunction, &func)
const wxEventType wxEVT_STRING_PAYLOAD = wxNewEventType();
//implementing test application
class MyApp : public wxApp
{
public:
virtual bool OnInit();
void OnProcessCustom(wxStringPayloadEvent& event);
};
bool
MyApp::OnInit()
{
//Connect event
//Connect(wxEVT_STRING_PAYLOAD, wxStringPayloadEventHandler(MyApp::OnProcessCustom));
Bind(wxEVT_STRING_PAYLOAD, &MyApp::OnProcessCustom, this);///< wish I could use this
wxStringPayloadEvent eventCustom;
eventCustom.SetEventObject(this);
eventCustom.setPayload(wxT("Test payload."));
wxPostEvent(this, eventCustom);
return true;
}
void MyApp::OnProcessCustom(wxStringPayloadEvent& event)
{
wxMessageBox(wxT("Event received. Payload = \"") + event.getPayload() + wxT("\""));
}
IMPLEMENT_APP(MyApp);
Here's the error message:
/ThirdParty/Includes/wx/event.h: In constructor 'wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>::wxEventFunctorMethod(void (Class::*)(EventArg&), EventHandler*) [with EventTag = int, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]':
/ThirdParty/Includes/wx/event.h:587: instantiated from 'wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>* wxNewEventFunctor(const EventTag&, void (Class::*)(EventArg&), EventHandler*) [with EventTag = int, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]'
/ThirdParty/Includes/wx/event.h:3182: instantiated from 'void wxEvtHandler::Bind(const EventTag&, void (Class::*)(EventArg&), EventHandler*, int, int, wxObject*) [with EventTag = wxEventType, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]'
../src/program.cpp:29: instantiated from here
/ThirdParty/Includes/wx/event.h:382: error: invalid conversion from 'wxEvent*' to 'wxStringPayloadEvent*'
/ThirdParty/Includes/wx/event.h:382: error: initializing argument 1 of 'static void wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>::CheckHandlerArgument(EventArg*) [with EventTag = int, Class = MyApp, EventArg = wxStringPayloadEvent, EventHandler = MyApp]'
Update more clues:
if you get an error here it means that the signature of the handler you're trying to use is not compatible with (i.e. is not the same as or a base class of) the real event class used for this event type
This is probably something that should be documented, but as far as I can see, you can't just declare your event type using 'const wxEventType ...' when you're using Bind(). Bind() requires the event type class which is provided when you use wxDEFINE_EVENT() instead. So, you actually need to make a few changes here.
1) Use this to define your event type (replacing 'const wxEventType ...'):
wxDEFINE_EVENT(wxEVT_STRING_PAYLOAD, wxStringPayloadEvent);
2) The above needs to be done after wxStringPayloadEvent has been defined obviously, so your wxStringPayloadEvent constructors can't just default to your custom event type. So here's what you're constructors for wxStringPayloadEvent should look more like:
wxStringPayloadEvent() : TemplatedPayloadEvent<wxString>(){};
wxStringPayloadEvent(wxEventType eventType) : TemplatedPayloadEvent<wxString>(eventType){};
3) Since you can't default your event type, you'll need to specify it in your custom event object construction:
wxStringPayloadEvent eventCustom(wxEVT_STRING_PAYLOAD);
I've tested these changes with SVN trunk, and it seems to work beautifully.