Unable to Handle wxEraseEvent?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
todd_machmotion
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Mar 14, 2016 4:24 pm

Unable to Handle wxEraseEvent?

Post by todd_machmotion »

I'm trying to solve some thread-timing issues, and I wanted to inspect the wxEraseEvent (WM_ERASEBKGND on Windows).
In my class that's a subclass of wxPanel, my event handler never gets called, even though I can verify with Spy++ that the WM_ERASEBKGND message is being send to my window. I can also put a breakpoint in wxWindowMSW::MSWHandleMessage() [src/msw/window.cpp] and see that the windows message is coming in for my object.

My attempt to bind a handler doesn't seem problematic.

Code: Select all

bool MyClass::Create(...) {
		// ...
		
		Bind( wxEVT_ERASE_BACKGROUND, [=]( wxEraseEvent& event ) {
				// emit a log message to a file
				event.Skip(true);
			});
			
		return true;
}
The project this is in is complex and doesn't lend itself to a minimal working example. There are other instances of classes where my event handler for this event _does_ get called.

I'm not using SetBackgroundStyle(). I can bind event handlers to other events (like wxEVT_PAINT).

What could I be doing that would affect whether or not the event handler gets invoked? Are there limitations on the quantity of handlers for wxEraseEvents? How could I verify that my handler is (properly) registered?

Any advice would be helpful. Thanks.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Unable to Handle wxEraseEvent?

Post by doublemax »

I can also put a breakpoint in wxWindowMSW::MSWHandleMessage() [src/msw/window.cpp] and see that the windows message is coming in for my object.
In that case, why didn't you step a little further into the code and see where it takes you? In the whole path there few conditions that could prevent the event handler from getting called, all which should not occur in your case.
There are other instances of classes where my event handler for this event _does_ get called.
Also other instances of the same class? Or is it only this class where it happens?
Are there limitations on the quantity of handlers for wxEraseEvents?
Not specifically for wxEraseEvents, but in general, if events are produced faster than the system can handle them, all kind of problems may occur. But in that case other events would get lost, too.
Use the source, Luke!
todd_machmotion
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Mar 14, 2016 4:24 pm

Re: Unable to Handle wxEraseEvent?

Post by todd_machmotion »

I wrote:I can also put a breakpoint in wxWindowMSW::MSWHandleMessage() [src/msw/window.cpp] and see that the windows message is coming in for my object.
In that case, why didn't you step a little further into the code and see where it takes you? In the whole path there few conditions that could prevent the event handler from getting called, all which should not occur in your case.
For instance, if I change the superclass (for the class in question) to a class that has a wxEraseEvent handler Bind()'d, the superclass's handler gets called, but not the subclass's.
In that case, why didn't you step a little further into the code and see where it takes you? In the whole path there few conditions that could prevent the event handler from getting called, all which should not occur in your case.
This is a good suggestion, especially if I understood how to inspect all the data structures where things are stored, like wxWindowMSW::gs_eraseBgHooks, though when I step through the code, looking up this in that particular hash never finds anything. The trouble is, it's tedious to do and I frequently don't know that I should have been stepping into a function until it's too late.

I'm using v3.0.1 (Released October 25, 2015). I don't know which precise revision of the files to use, but I'll use my line numbers (v3.0.1) whereas the linked files may be (some) different.

In this case, window.cpp:3329, I always see it take wxWindowMSW::HandleEraseBkgnd(). Eventually this goes down into wxWindowMSW::HandleEraseBkgnd() and then the generic wxWindowBase::HandleWindowEvent(). In the end, it looks like I'll have to manually inspect the dynamic event table if I want to be sure the handler is bound/registered.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Unable to Handle wxEraseEvent?

Post by doublemax »

For instance, if I change the superclass (for the class in question) to a class that has a wxEraseEvent handler Bind()'d, the superclass's handler gets called, but not the subclass's.
That's interesting. Is the base class already fully created when you make the Bind call?

For a test, can you try using a static event table entry?
Use the source, Luke!
todd_machmotion
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Mar 14, 2016 4:24 pm

Re: Unable to Handle wxEraseEvent?

Post by todd_machmotion »

I tried obsessively adding handlers for the various children that I create, then watching which objects the WM_ERASEBKGND come in on. It seems that the events are not coming in on all objects, but they are on some.

Is it possible that Windows doesn't send erase events to a window if it doesn't have meaningful (direct-descendant) children? I.e. it's a panel that only contains another panel?

Edit: I was watching the wx event handling of WM_ERASEBKGND, and never saw it happen for the class in question, only for the panel it creates where all the other controls go. I don't know that the object isn't getting a WM_ERASEBKGND message.
Last edited by todd_machmotion on Wed Sep 19, 2018 8:57 pm, edited 1 time in total.
todd_machmotion
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Mar 14, 2016 4:24 pm

Re: Unable to Handle wxEraseEvent?

Post by todd_machmotion »

doublemax wrote:
For instance, if I change the superclass (for the class in question) to a class that has a wxEraseEvent handler Bind()'d, the superclass's handler gets called, but not the subclass's.
That's interesting. Is the base class already fully created when you make the Bind call?

For a test, can you try using a static event table entry?
I'm doing the Bind() inside Create(), near the end. I developed a scheme to dump the dynamic event table, and I can find my handler(s) in there. It seems that some of the objects just don't get a WM_ERASEBKGND from Windows, and so I have to bind the handlers to the correct objects.
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Unable to Handle wxEraseEvent?

Post by doublemax »

I'm doing the Bind() inside Create(), near the end.
Yes, but do you call Create() for the base class or create it in any other way?
Use the source, Luke!
todd_machmotion
Earned a small fee
Earned a small fee
Posts: 14
Joined: Mon Mar 14, 2016 4:24 pm

Re: Unable to Handle wxEraseEvent?

Post by todd_machmotion »

doublemax wrote:
I'm doing the Bind() inside Create(), near the end.
Yes, but do you call Create() for the base class or create it in any other way?
The base class is getting created by the default constructor, my constructor is calling Create(), which is, in turn, calling the base class's Create(). All the Bind()ing is happening after all that.

It is legal to have multiple event handlers for the same event for the same wxEvtHandler object, yes?
User avatar
doublemax
Moderator
Moderator
Posts: 19160
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Unable to Handle wxEraseEvent?

Post by doublemax »

It is legal to have multiple event handlers for the same event for the same wxEvtHandler object, yes?
Probably yes. (not 100% sure though). But only the the first one will get executed unless it calls "wxEvent::Skip()".
Use the source, Luke!
Post Reply