Как получить форму MDIMain, чтобы получить сообщение о закрытии приложения перед формами mdichild

Наше приложение использует «MDI» (большинство проблем исправлено в потомках TForm). В большинстве форм, если данные были изменены, они отказываются закрыться (используя closequery) и предлагают пользователю сохранить или отменить. Это прекрасно работает.

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

Проблема в том, что CloseQuery MainForm срабатывает после всех форм mdichild. Я пробовал wm_close, wm_quit и даже windproc в MainForm. Но они не стреляют вовремя.

Когда я получаю formclosequery в mdichild, у меня нет возможности узнать, уничтожается ли эта форма пользователем или уничтожается приложение.

Наверняка есть простой способ сделать это. Что я пропустил?


person Rohit Gupta    schedule 03.03.2017    source источник
comment
Можете ли вы показать, как вы обрабатываете WM_CLOSE в своей основной форме?   -  person David Heffernan    schedule 03.03.2017
comment
@ken, это MS, обратная совместимость - это главное, работает так же, как и всегда, шепните, но мое приложение - mdi.....   -  person David Heffernan    schedule 03.03.2017
comment
@ Дэвид: Да, я знаю. Вы не видели ;-) в конце?   -  person Ken White    schedule 03.03.2017
comment
Нажатие на X MainForm сначала уведомит MainForm, а затем уведомит его дочерние формы. Если у вас возникли проблемы с обработкой первоначального уведомления в WndProc(), вероятно, вы неправильно его обрабатываете. Пожалуйста, покажите ваш реальный код.   -  person Remy Lebeau    schedule 03.03.2017
comment
Это кажется странным поведением клиентов. Вы уверены, что правильно их поняли?   -  person Rob Kennedy    schedule 03.03.2017


Ответы (1)


Объяснение такому поведению можно найти в реализации TCustomForm.CloseQuery, которая выглядит так:

function TCustomForm.CloseQuery: Boolean;
var
  I: Integer;
begin
  if FormStyle = fsMDIForm then
  begin
    Result := False;
    for I := 0 to MDIChildCount - 1 do
      if not MDIChildren[I].CloseQuery then Exit;
  end;
  Result := True;
  if Assigned(FOnCloseQuery) then FOnCloseQuery(Self, Result);
end;

Код вызывает CloseQuery для каждого дочернего элемента MDI, который запускает любые события OnCloseQuery, прикрепленные к дочерним элементам MDI, а затем запускает событие OnCloseQuery для основной формы MDI.

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

Например, вы можете сделать это в своей основной форме:

// in the form type declaration:
function CloseQuery: Boolean; override;

// in the implementation section:
function TMainForm.CloseQuery: Boolean;
begin
  Result := True;
  if Assigned(OnCloseQuery) then OnCloseQuery(Self, Result);
end;

Или, может быть, так:

function TMainForm.CloseQuery: Boolean;
begin
  while MDIChildCount > 0 do
    MDIChildren[0].Free;
  inherited;
end;

Или даже:

function TMainForm.CloseQuery: Boolean;
begin
  Application.Halt;
end;
person David Heffernan    schedule 03.03.2017