Delphi - переопределение скрытого поведения TForm.showModal

В настоящее время я пишу систему управления окнами для существующего приложения Delphi.

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

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

Есть ли способ предотвратить автоматическое скрытие модальных форм после завершения их процесса? Это позволило бы мне вручную скрыть их, как только родительская форма снова станет видимой. Я пытался запланировать это в событии FormHide каждой дочерней формы, но это не работает, так как дочерняя форма также скрывается при открытии одного из ее собственных дочерних элементов.

РЕДАКТИРОВАТЬ:

Вот то, что я до сих пор основывал на совете Реми ниже

procedure openModalChild(child: TForm; parent: TForm);
var
  WindowList: Pointer;
  SaveFocusCount: Integer;
  SaveCursor: TCursor;
  SaveCount: Integer;
  ActiveWindow: HWnd;
  Result: integer;
begin
  CancelDrag;
  with child do begin
  Application.ModalStarted;
  try
  ActiveWindow := GetActiveWindow;
  WindowList := DisableTaskWindows(0);
  //set the window to fullscreen if required
  setScreenMode(child);
  try
    Show; //show the child form
    try
      SendMessage(Handle, CM_ACTIVATE, 0, 0);
      ModalResult := 0;
      repeat
        Application.HandleMessage;
        //if Forms.Application.FTerminate then ModalResult := mrCancel else
          if ModalResult <> 0 then closeModal(child as TCustomForm);
      until ModalResult <> 0;
      Result := ModalResult;
      SendMessage(Handle, CM_DEACTIVATE, 0, 0);
      if GetActiveWindow <> Handle then ActiveWindow := 0;
    finally
      parent.Show;
      Hide;
    end;
  finally
    EnableTaskWindows(WindowList);
    parent.Show; //reshow the parent form
    if ActiveWindow <> 0 then SetActiveWindow(ActiveWindow);
  end;
  finally
    Application.ModalFinished;
  end;
  end;
end;

Это работает хорошо, но единственная проблема в том, что активный цикл повторения никогда не прерывается, даже после того, как дочерний элемент был экранирован, и поэтому родительская форма никогда не перезапускается Есть ли способ, которым я могу решить это?

1 ответ

Решение

ShowModal() явно вызывает Show() непосредственно перед входом в его цикл модальной обработки и явно вызывает Hide() сразу после выхода из цикла. Вы не можете изменить это без изменения кода в исходном файле VCL Forms.pas.

Если вам нужно более точное управление окнами без редактирования исходного кода VCL, не используйте ShowModal() совсем. использование Show(), Hide(), DisableTaskWindows(), а также EnableTaskWindows() себя по мере необходимости. Я бы посоветовал вам взглянуть на Forms.pas, чтобы увидеть, как они используются. Скопируйте реализацию ShowModal() в свою собственную функцию, то вы можете настроить его по мере необходимости.

Другие вопросы по тегам