在消息处理程序中调用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
?我什么时候应该使用?
答案 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 );
编译将失败。
另一个问题是哪个祖先重写了什么。因此,一个祖先可能会覆盖消息处理程序,而另一个祖先可能会覆盖默认处理程序,这使得它在没有大量挖掘的情况下会非常混乱。
所以我想对我来说,我必须依靠最好的文档。这意味着,一般来说,我会使用继承,因为我回到了这个特定消息的祖先实现,而不是一般的消息的祖先实现。
我猜这是另一种说法 - 我会采用维多利亚的方法。