В чем разница между 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 );

сбой компиляции.

Другая проблема заключается в том, что предок переопределяет то, что. Таким образом, один предок может переопределить обработчик сообщений, а другой может переопределить обработчик по умолчанию, что делает его очень запутанным без большого рытья.

Итак, я думаю, для меня я должен отказаться от того, что лучше всего подходит для документации. Это означает, что в общем случае я бы использовал унаследованный, потому что я возвращаюсь к реализации данного предка предков, а не к реализации предков для сообщений вообще.

Я думаю, это другой способ сказать: я бы пошел с подходом Виктории.