Issues with custom events - wxWidgets 3.0.5

403 views
Skip to first unread message

Richard Závodný

unread,
Dec 15, 2020, 6:05:03 AM12/15/20
to wx-users
Hello, I'm coming here for help about custom events. My application works with DirectInput API (it's not a game just to mention) and I have written my own "wrapper" around it. Let me explain my project structure:

cApp -> the very main class that inherits from wxApp
mainFrame -> class that inherits from wxFrame with my main (and only) window, here is the whole GUI, Binded events for buttons, etc.

so far everything is fine, now I need to add this functionality:
dIHandler -> class for my very own DirectInput API wrapper that don't inherit from any wx class

Basically dIHandler constantly reads device (joystick, etc.) data and I need to update GUI elements in mainFrame (some sliders, text inputs) accordingly. I need few events, for when the device gets connected to the PC (diEVT_DI_DEVICE_CONNECTED), when it gets disconnected (diEVT_DI_DEVICE_DISCONNECTED), gets polled (diEVT_DI_DEVICE_POLLED) and some other events. I also need to send some data through the event (poll event). 

So what is my problem you are asking? I tried to implement this, but I'm having issues. I created class dIEvent, that inherits from wxEvent, included it in dIHandler.h and proceeded as explained here.

Here is part of the important code of what I have tried and it doesn't work: https://pastebin.com/brT5JkAX

The error I'm getting is this:
error C2664: 'wxEvtHandler *wxPrivate::HandlerImpl<Class,EventArg,true>::ConvertToEvtHandler(T *)': cannot convert argument 1 from 'EventHandler *const ' to 'T *'

Also can you direct me the right way with multithreading? As I need to constantly read DirectInput data and at the same time constantly updating the GUI. Thank you! 

PB

unread,
Dec 15, 2020, 6:50:57 AM12/15/20
to wx-users
Hi,

I only skimmed your code so I might have missed something, sorry. I did not find wxDEFINE_EVENT() in your source file, you need to have the declaration in the header and definition in the source. You have the declaration in both, which is wrong.

You can see a complete example of creating and using a new event in the event sample (it is not there in v3.0, only in 3.1), see here

And here is a simple example of a worker thread using events to update the GUI in the main thread:

Disclaimer: I wrote all the referenced code, no warranties.

Regards,
PB

Richard Závodný

unread,
Dec 15, 2020, 8:58:24 AM12/15/20
to wx-users
I think that there is problem that dIHandler is not inheriting from any wx class. Because it's not GUI and it's not GUI element that sends out those events in my case. 

PB

unread,
Dec 15, 2020, 9:34:31 AM12/15/20
to wx-users
When using Bind(), the handler does not need to inherit from wxEvtHandler, please see

It does have to have a matching signature though, i.e., it must take an appropriate wxEvent or derived as a reference as the function parameter.

Did you fix the issue with a missing event type definition, or it was not actually missing and I overlooked it?

BTW, the code link to wxForum for using events with threads I provided before is known to crash on wxWidgets 3.0. Sorry, I forgot about that. I works reliably on 3.1 but that is probably just a coincidence and the code must have a bug I cannot figure out.

Regards,
PB


Richard Závodný

unread,
Dec 15, 2020, 9:37:52 AM12/15/20
to wx-users
It doesn't, still the same error as I mentioned. 


error C2664: 'wxEvtHandler *wxPrivate::HandlerImpl<Class,EventArg,true>::ConvertToEvtHandler(T *)': cannot convert argument 1 from 'EventHandler *const ' to 'T *'

It's ok, I'll upgrade to 3.1 later. :) 

PB

unread,
Dec 15, 2020, 10:25:15 AM12/15/20
to wx-users
I do not think wxWidgets version is of any relevance here.

What I find very odd is
Bind(diEVT_DI_DEVICE_POLLED, &mainFrame::devPolled, this);

I think that instead of this, there needs to be an instance of mainFrame which will actually handle the event.

Additionally, if that Bind() call in dIHandler()'s ctor were to happen in the worker thread, I think that would be incorrect too but it would be a run-time problem, not a compile-time one.

Regards,
PB


Richard Závodný

unread,
Dec 15, 2020, 11:30:12 AM12/15/20
to wx-users
That instance is however made in cApp class. So how do I reach that? Shouldn't the Bind then be in mainFrame? 

My thought is that I will handle the event "locally" in dIHandler and will refer it to the function specified in second parameter, which is mainFrame::devPolled(). 

Richard Závodný

unread,
Dec 15, 2020, 11:31:30 AM12/15/20
to wx-users
So what I need is pretty much to send event from dIHandler and process it in mainFrame. 

PB

unread,
Dec 15, 2020, 11:58:37 AM12/15/20
to wx-users
I think the Bind call should probably happen within a frame, where the handler method is, it makes most sense.

And you somehow need to make the handling instance of the frame available to dIHandler, which would then call wxQueueEvent(frameInstance, event.Clone()). Or you need to find some other way for the event to reach the frame, check the Event Handling Overview to see how the events are propagated.

Richard Závodný

unread,
Dec 30, 2020, 9:47:51 AM12/30/20
to wx-users
Sorry for late reply, as I was working on different projects, this one had to been put into the drawer for a while. However I managed to make it work, I'm not using custom event derived from wxEvent class, but I made few custom events derived from wxThreadEvent and it works very well! However, I still have something on my heart... What kind of thread type I should use (JOINABLE vs. DETACHED)?
Reply all
Reply to author
Forward
0 new messages