Как перехватывать события активации дочерней формы в mdi приложении?

Рейтинг: 1Ответов: 1Опубликовано: 29.04.2015

Хочу словить событие активации child формы в mdi приложении. Пытаюсь это сделать с помощью хелперов:

TFormHelper = class helper for TForm
public
  procedure WMMDIACTIVATE(var msg: TWMMDIACTIVATE); message WM_MDIACTIVATE;
end;

...

procedure TFormHelper.WMMDIACTIVATE(var msg: TWMMDIACTIVATE);
begin
  ShowMessage('1');
end;

В чем тут ошибка? Может есть более правильный способ отловить активацию формы? Знаю что можно написать обертку на TForm и наследоваться от нее, но не хотелось бы менять родителя во всех формах.

Ответы

▲ 2

Понятия не имею, как это на самом деле реализовано (и вообще на дельфи не программирую), а гугл упорно ничего находить не хочет, поэтому описанное ниже считать гипотезой. Помогло бы, если бы вы включили текст ошибки, если таковая присутствует.

Class helper — синтаксический сахар над статическими функциями, которые первым (неявным) параметром принимают self, как и обычные инстансные функциии. Хелперы и их методы никаким образом не сказываются на иерархии классов, поэтому в них не может быть виртуальных методов.

Функции с атрибутом message — это синтаксический сахар над WndProc (var Msg: TMessage); override; с case по всем сообщениям, которые есть в объявлении класса, и вызовом WndProc базового типа.

Как можно видеть, эти две синтаксические конструкции несовместимы в принципе. Добавление хелпера не может влиять на поведение всех существующих классов-наследников от заданного типа — это всего лишь набор отдельных функций.

Правильный способ — это переопределять WndProc в нужных вам формах. По крайней мере, если нет возможности подписаться на событие извне, то есть событие WM_MDIACTIVATE не вытащено во внешний интерфейс (полагаю, что не вытащено, иначе вы бы не спрашивали). Ещё есть костыли через SetWindowLong с GWL_WNDPROC, но лучше этим не пользоваться, потому что весь смысл VCL в том, чтобы скрывать эти детали, и шут знает, чем обернётся заход с заднего крыльца.