Jeremy White wrote:
Question: is this a bug? The only alternate behaviour I can come up with is that SetEvent(), rather than setting the NEM flag, should check it and bail out if it is not set (with a warning?). [The current behaviour is useful if you are sub-classing a control, and do not know which method a user of the control will want to use.]

Surely running both NEM and OEM code for the same event is a bug? In other words, a successful NEM call still causes the OEM logic to be run. If you happen to have an sub that matches, then you get two events being processed for a single event. See the code below for a better explanation:)

Well, you could certainly argue that it is a bug, but I don't really know what the thinking was when this was originally written. There's certainly an option -eventmodel => 'both', which explicitly allows this (i.e. sets both the OEM and NEM flag).

As I see the logic in DoEvents (psudeo-code):

PerlResult = 1;
// NEM event
if((perlud->dwPlStyle & PERLWIN32GUI_NEM) && (perlud->dwEventMask & iEventId)) {
    PerlResult = 0;
    PerlResult = NEM_CALLBACK;
        .....
}

// OEM Event
if (PerlResult == 1 && (perlud->dwPlStyle & PERLWIN32GUI_OEM) && perlud->szWindowName != NULL) {
    PerlResult = 0;
    if there is a function called main::perlud->szWindowName_EventName {
        PerlResult = OEM_CALLBACK;
        ......
   }
}

This says do the NEM event if the NEM flag is set and there's a coderef set for the event. Then do the OEM Event if:
- Either there was no NEM event, or the NEM event returned 1
- And the OEM flag is set
- And the window has a name
- And the correctly name callback function exists

So in my last analysis I missed the 3rd way not to get the OEM event fired: returning 1 from the NEM handler.

I personally don't see anything wrong with this logic, so long as you believe that returning 1 from an event handler means 'pass the event to the next handler', regardless of whether this is another event handler, or defwindowproc. Although I note that DoHook doesn't implement such logic if you have multiple hooks for the same event.

So, we come back to whether the SetEvent logic is right. Currently SetEvent replaces any NEM coderef for the event passed, or creates one if there wasn't one there before, and ensures that the NEM flag is set. As in my previous email, the only alternative I see is to get SetEvent to choke if the NEM flag is not set.

I take back my position on not wanting to change this: having looked at my code I use hooks rather than SetEvent, in order not to interfer with what the user of my sub-classes intends. I am, thus, indifferent on making such a change, although I might argue that if you only want NEM, then you need to indicate that when you create the object. Do you have an alternative on what you think would be correct behaviour?

Regards,
Rob.

Reply via email to