В чем разница между DefaultHandler (Message) и "inherited" в обработчиках сообщений?
В чем разница между вызовами DefaultHandler(Message)
и inherited
в обработчиках сообщений. например:
TScrollBox = class(TScrollingWinControl)
private
...
procedure WMNCHitTest(var Message: TMessage); message WM_NCHITTEST;
...
end;
procedure TScrollBox.WMNCHitTest(var Message: TMessage);
begin
DefaultHandler(Message);
end;
Почему бы не позвонить inherited
здесь? когда я должен использовать либо?
Ответы
Ответ 1
Рассмотрим пример, который вы предоставляете. Предположим, что вместо вызова 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;
При проектировании выполняется специальное лечение, в противном случае оно вызывает унаследованное, что в конечном итоге приводит к вызову DefaultHandler
, который пересылает сообщение в оконную процедуру по умолчанию.
Теперь TScrollBox
заменяет этот обработчик сообщения следующим образом:
procedure TScrollBox.WMNCHitTest(var Message: TMessage);
begin
DefaultHandler(Message);
end;
Он вызывает DefaultHandler
напрямую и поэтому безоговорочно пересылает сообщение в процедуру окна по умолчанию.
Итак, из этого заключаем, что TScrollBox.WMNCHitTest
просто меняет поведение во время проектирования, подавляя код в TWinControl.WMNCHitTest
, который возвращает HTCLIENT
.
Поэтому я предполагаю, что это была мотивация автора этого кода VCL. Используя DefaultHandler
, поведение базового окна (как определено процедурой окна по умолчанию) восстанавливается, удаляя любые модификации поведения, реализованные промежуточным кодом VCL.
Ответ 2
Очень сложно быть уверенным в конкретных случаях. DefaultHandler обрабатывает (теоретически) все сообщения, в которых обработчик сообщений обрабатывает только один. Обработчик по умолчанию является общедоступным виртуальным методом и поэтому может быть явно переопределен. Обработчики сообщений не объявляются виртуальными и обычно являются приватными, так, например, в вашем коде, если вы замените
inherited;
по
inherited WMNCHitTest( message );
сбой компиляции.
Другая проблема заключается в том, что предок переопределяет то, что. Таким образом, один предок может переопределить обработчик сообщений, а другой может переопределить обработчик по умолчанию, что делает его очень запутанным без большого рытья.
Итак, я думаю, для меня я должен отказаться от того, что лучше всего подходит для документации. Это означает, что в общем случае я бы использовал унаследованный, потому что я возвращаюсь к реализации данного предка предков, а не к реализации предков для сообщений вообще.
Я думаю, это другой способ сказать: я бы пошел с подходом Виктории.