以模式窗口的形式显示MDI表单

4

这可能与 MDI 的本质相悖,但我有时需要将一个 MDI 表单(FormStyle=fsMdiChild)显示为模态。我还需要访问另一个 MDI 表单的 Application.CreateForm 和 OnShow 事件之间的部分。

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

有什么想法吗?
4个回答

5

对于您的第一个问题:添加另一个构造函数,例如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,并调用继承的create函数。
你还需要两个东西,相当容易理解:
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; 

现在,如果使用标准构造函数创建表单模态框,则可以调用表单模态框。如果使用CreateAsMDI创建,则可以将其作为MDI子窗口调用。
如果您在表单的声明中包含此内容:
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网站的一篇文章中翻译了这个答案。

(如果您使用的是 OldCreateOrder 设置为 True 的表单)则应在 TModalAndMDIForm.CreateAsMDI 结尾处添加 if OldCreateOrder then DoCreate - yonojoy
原始代码的链接已经失效。这里提供一个修改后的可用版本 - yonojoy

2

最简单的方法是创建一个简单的表单子类,并在属性检查器中设置

FormStyle = fsMDIChild

以及

Form.Visible = False

这是经过试验和测试的!保留HTML标签。


有些 Delphi 版本无法在属性检查器中设置这些属性组合。它可以在 Delphi 2009 中工作,但我不知道从哪个版本开始。不过这是一个非常微不足道的事情,我认为 OP 正在使用一个不支持该选项的 Delphi 版本。 - mghie
我想我最初在Delphi 6上做的项目。从记忆中,重要的是以正确的顺序设置属性 - 除非我直接编辑了DFM(太久远了,记不清了)。 - Gerry Coll

1

以上没有一个回答能够完成所需的工作。最佳答案也是错误的,因为以下原因:

  • 打开第一个表单;
  • 将其最大化;
  • 现在说这个表单调用另一个表单(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;

1
至少对于 Delphi 2007 和 2009,创建 MDI 子窗体不可见很容易。对于早期的 Delphi 版本(在该版本中无法在属性检查器中设置 VisibleFalse),您只需要为 OnCreate 事件提供一个处理程序,并访问该类的受保护字段即可:
procedure TMDIChild.FormCreate(Sender: TObject);
begin
  FFormState := FFormState - [fsVisible];
end;

这将禁用 MDI 子窗体的自动显示。在完成其他初始化后,您可以简单地 Show 它或将 Visible 设置为 True

我不会尝试回答关于模态 MDI 子窗体的问题,因为这违反了 Windows 平台的惯例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接