消息处理程序中的DefaultHandler(Message)和“inherited”有什么区别?

时间:2017-06-26 08:00:04

标签: delphi

在消息处理程序中调用DefaultHandler(Message)inherited之间的区别是什么? 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;

为什么不在这里拨打inherited?我什么时候应该使用?

2 个答案:

答案 0 :(得分:5)

让我们考虑一下您提供的示例。假设不是调用DefaultHandler,而是调用了继承(或等效地没有WM_NCHITTEST消息处理程序由TScrollBox实现)。在这种情况下,消息将由TWinControl在此方法中处理:

procedure TWinControl.WMNCHitTest(var Message: TWMNCHitTest);
begin
  with Message do
    if (csDesigning in ComponentState) and (FParent <> nil) then
      Result := HTCLIENT
    else
      inherited;
end;

这在设计时会执行特殊处理,否则会调用inherited,最终导致调用DefaultHandler,将消息转发到默认窗口过程。

现在,TScrollBox将此消息处理程序替换为:

procedure TScrollBox.WMNCHitTest(var Message: TMessage);
begin
  DefaultHandler(Message);
end;

直接调用DefaultHandler,因此无条件地将消息转发到默认窗口过程。

因此,我们从中得出的结论是TScrollBox.WMNCHitTest只是通过抑制返回TWinControl.WMNCHitTest的{​​{1}}中的代码来改变设计时的行为。

因此,我认为这是本VCL代码作者的动机。通过使用HTCLIENT,可以恢复底层窗口的行为(由默认窗口过程确定),从而删除由插入的VCL代码实现的任何行为修改。

答案 1 :(得分:2)

在特定情况下很难确定。 DefaultHandler处理(理论上)所有消息,其中消息处理程序只处理一个消息。默认处理程序是一个公共虚拟方法,因此可以显式覆盖。消息处理程序未声明为虚拟,并且通常是私有的,因此例如在您的代码中替换

inherited;

通过

inherited WMNCHitTest( message );

编译将失败。

另一个问题是哪个祖先重写了什么。因此,一个祖先可能会覆盖消息处理程序,而另一个祖先可能会覆盖默认处理程序,这使得它在没有大量挖掘的情况下会非常混乱。

所以我想对我来说,我必须依靠最好的文档。这意味着,一般来说,我会使用继承,因为我回到了这个特定消息的祖先实现,而不是一般的消息的祖先实现。

我猜这是另一种说法 - 我会采用维多利亚的方法。