What exactly is the difference between calling DefaultHandler(Message)
and inherited
in a message handlers. e.g:
TScrollBox = class(TScrollingWinControl)
private
...
procedure WMNCHitTest(var Message: TMessage); message WM_NCHITTEST;
...
end;
procedure TScrollBox.WMNCHitTest(var Message: TMessage);
begin
DefaultHandler(Message);
end;
Why not call inherited
here? when should I use either?
Let us consider the example that you provide. Suppose that instead of calling DefaultHandler
, inherited was called (or equivalently no WM_NCHITTEST
message handler was implemented by TScrollBox). In that scenario the message would be processed by TWinControl
in this method:
procedure TWinControl.WMNCHitTest(var Message: TWMNCHitTest);
begin
with Message do
if (csDesigning in ComponentState) and (FParent <> nil) then
Result := HTCLIENT
else
inherited;
end;
This performs special treatment when designing, otherwise it calls inherited which ultimately leads to a call to DefaultHandler
which forwards the message to the default window procedure.
Now, TScrollBox
replaces that message handler with this one:
procedure TScrollBox.WMNCHitTest(var Message: TMessage);
begin
DefaultHandler(Message);
end;
That calls DefaultHandler
directly, and so unconditionally forwards the message to the default window procedure.
So, what we conclude from this is that TScrollBox.WMNCHitTest
simply changes behaviour at designtime by suppressing the code in TWinControl.WMNCHitTest
which returns HTCLIENT
.
I presume therefore that this was the motivation of the author of this VCL code. By using DefaultHandler
the behaviour of the underlying window (as determined by the default window procedure) is restored, removing any behaviour modifications implemented by the intervening VCL code.
It is very hard to be sure in specific cases. DefaultHandler handles (in theory) all messages where a message handler handles only one. Default Handler is a public virtual method and so can be overridden explicitly. Message handlers are not declared virtual, and are usually private anyway, so for example in your code if you replace
inherited;
by
inherited WMNCHitTest( message );
the compile will fail.
The other issue is which ancestor overrides what. So one ancestor may override the Message Handler, and another may override Default Handler, which makes it very confusing without a lot of digging.
So I guess for me I have to fall back on what seems best for documentation. Which means, in general, I would use inherited, because I am falling back on the ancestors implementation of this particular message, not the ancestors implementation for messages in general.
Which I guess is another way of saying - I would go with Victoria's approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With