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.
I see your point. The problem is that most handlers don't explicitly return
anything, which means we would always return 1. This in turn forces OEM
logic to be run for any NEM event created by SetEvent.
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?
I would argue that the logic in SetEvent is wrong. My rational is as
follows:
There are two main reasons to use SetEvent:
1) To add NEM events to windows/controls after they have been created -
perhaps by a 3rd party tool (such as Loft) which isn't NEM aware.
2) To change the event handlers during runtime.
In both cases, the expectation should be that the control is now running
under NEM only - just as if the control was created with NEM event handlers
in the first place.
If these assumptions are correct - and I could be wrong - shouldn't the
approach be to simply turn off the OEM for a control that uses SetEvent?
Instead of (in SetEvent):
perlud->hvEvents = perlcs.hvEvents;
perlud->dwEventMask = perlcs.dwEventMask;
SwitchBit(perlud->dwPlStyle, PERLWIN32GUI_NEM, (perlud->dwEventMask !=
0));
XSRETURN_YES;
we have:
perlud->hvEvents = perlcs.hvEvents;
perlud->dwEventMask = perlcs.dwEventMask;
SwitchBit(perlud->dwPlStyle, PERLWIN32GUI_NEM, (perlud->dwEventMask !=
0));
SwitchBit(perlud->dwPlStyle, PERLWIN32GUI_OEM, 0);
XSRETURN_YES;
The control would now operate fully under NEM.
Thoughts?
Cheers,
jez.