Отображение формы MDI как модальной

Это будет звучать против природы MDI. Иногда мне нужно показать форму MDI (FormStyle=fsMdiChild) как модальную. И мне также нужно получить доступ к части между Application.CreateForm и событием OnShow другой формы MDI, т.е.

Application.CreateForm(Form2,TForm2); // but don't set form2's visible property true.
Form2.caption:='not working example'; 
Form2.SomeMagicToSetVisibleTrue;

Любые идеи?


person Ertugrul Kara    schedule 22.09.2009    source источник


Ответы (4)


Для вашей первой проблемы: добавьте еще один конструктор, например CreateAsMDI, например:

constructor TModalAndMDIForm.CreateAsMDI(AOwner: TComponent); 
begin 
  f_blChild := true; 
  GlobalNameSpace.BeginWrite; 
  try 
    inherited CreateNew(AOwner); 
    if(not(csDesigning in ComponentState)) then begin 
      Include(FFormState, fsCreating); 
      try 
        FormStyle := fsMDIChild; 
        if(not(InitInheritedComponent(self, TForm))) then 
          raise Exception.CreateFmt('Can't create %s as MDI child', [ClassName]); 
      finally 
        Exclude(FFormState, fsCreating); 
      end; 
    end; 
  finally 
    GlobalNameSpace.EndWrite; 
  end; 
end; 

В обычном конструкторе просто установите переменную f_blChild в false и вызовите унаследованное создание.

Вам нужны еще две вещи, скорее самообъясняющие:

procedure TModalAndMDIForm.Loaded; 
begin 
  inherited; 
  if(f_blChild) then 
    Position := poDefault 
  else begin 
    Position := poOwnerFormCenter; 
    BorderStyle := bsDialog; 
  end; 
end; 
//----------------------------------------------------------------------------- 
procedure TModalAndMDIForm.DoClose(var Action: TCloseAction); 
begin 
  if(f_blChild) then 
    Action := caFree; 
  inherited DoClose(Action); 
end; 

Теперь вы можете вызывать форму модальной, если она создана с помощью стандартного конструктора, и как дочернюю форму MDI, если она создана с помощью CreateAsMDI.

Если вы включите это в объявление формы

property IsChild: boolean read f_blChild; 

вы даже можете делать что-то в зависимости от того, является ли форма дочерним элементом MDI или нет, просто опрашивая свойство isChild.

Что касается вашей второй проблемы: не используйте Application.CreateForm, а создайте свою форму самостоятельно:

Вот два творения для модала и MDI:

//Modal 
frmDialog := TMyForm.Create(self); 
// Your Code
frmDialog.ShowModal; 
frmDialog.Release; 

//MDI-Child 
frmDialog := TMyForm.CreateChild(self); 
// Your code
frmDialog.Show;

Я перевел этот ответ из статьи на сайте DelphiPraxis.

person Ralph M. Rickenbach    schedule 22.09.2009
comment
(Если вы используете форму, в которой OldCreateOrder установлено на True), вы должны добавить if OldCreateOrder then DoCreate в конце TModalAndMDIForm.CreateAsMDI. - person yonojoy; 18.09.2019
comment
Ссылка на исходный код битая. Вот измененная рабочая версия. - person yonojoy; 18.09.2019

Самый простой способ - создать тривиальный подкласс формы и установить

FormStyle = fsMDIChild

И

Form.Visible = False

в инспекторе по имуществу. Это проверено и проверено!

person Gerry Coll    schedule 22.09.2009
comment
Были версии Delphi, в которых нельзя было установить эту комбинацию свойств в инспекторе свойств. Он работает в Delphi 2009, но я не знаю, с какой версии. Это настолько тривиально, что я предположил, что OP использует версию Delphi, где это невозможно. - person mghie; 23.09.2009
comment
Я думаю, что проект, в котором я впервые сделал это, был в Delphi 6 в то время. По памяти важно установить свойства в правильном порядке - если только я не редактировал DFM напрямую (слишком давно, чтобы помнить) - person Gerry Coll; 23.09.2009

По крайней мере, для Delphi 2007 и 2009 легко создать невидимую дочернюю форму MDI. Для ранних версий Delphi (где было невозможно установить Visible в False в инспекторе свойств) вам просто нужно было предоставить обработчик события OnCreate и получить доступ к защищенному полю класса:

procedure TMDIChild.FormCreate(Sender: TObject);
begin
  FFormState := FFormState - [fsVisible];
end;

Это отключит автоматическое отображение дочернего MDI. После того, как вы закончите с другими инициализациями, вы можете просто Show его или установить Visible в True.

Я не буду пытаться ответить на ваш вопрос о модальных дочерних формах MDI, так как это нарушает соглашения платформы Windows.

person mghie    schedule 22.09.2009

Никакие ответы выше на самом деле не выполняют требуемую работу. Лучший ответ также неверен из-за следующего:

  • Открытие первой формы;
  • Максимизируйте это;
  • Теперь скажем, что эта форма вызывает другую форму (mdi);
  • Когда он построен таким же образом, вы получите глючный макет... (он будет mdi дочерним, но не максимизированным, однако первый все равно будет максимизированным). Итак, глючное состояние.

Если вам действительно нужно решить во время выполнения, является ли это fsMDIChild или fsNormal, вам нужно применить следующий подход.

  1. У вас есть форма, которая хранится как fsNormal в дизайне (или наоборот);
  2. Переопределите метод InitializeNewForm;
  3. Установите для FFormStyle значение fsMDIChild (как показано ниже).

...

TYourForm = class(TForm)
...
protected
  procedure InitializeNewForm; override;
...

procedure TYourForm.InitializeNewForm;
var
  FS: ^TFormStyle;
begin
  inherited;
  if DoYourCheckForMDI then
    begin
      FS := @FormStyle;
      FS^ := fsMDIChild;
    end;
end;
person Z.B.    schedule 17.04.2015