Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between DefaultHandler(Message) and "inherited" in message handlers?

Tags:

delphi

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?

like image 559
zig Avatar asked Jun 26 '17 08:06

zig


2 Answers

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.

like image 195
David Heffernan Avatar answered Sep 17 '22 18:09

David Heffernan


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.

like image 40
Dsm Avatar answered Sep 20 '22 18:09

Dsm