将 MDI 表单显示为模式

发布于 2024-08-05 15:01:43 字数 325 浏览 1 评论 0 原文

这听起来违背了 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;

有什么想法吗?

This will sound against the nature of MDI.. I need to show a MDI form (FormStyle=fsMdiChild) as modal sometimes. And I also need to access the part between Application.CreateForm and OnShow event of another MDI form, i.e.

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

Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

寂寞陪衬 2024-08-12 15:01:43

对于第一个问题:添加另一个构造函数,例如 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; 

现在您可以调用表单模式(如果使用标准构造函数创建),以及作为 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

For your first problem: Add another constructor, for example CreateAsMDI, like this:

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; 

In the normal constructor just set the variable f_blChild to false and call the inherited create.

You need two more things, rather self explaining:

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; 

Now you can call the form modal, if created with the standard constructor, and as MDI child, if created with CreateAsMDI.

If you include this in your form's declaration

property IsChild: boolean read f_blChild; 

you can even do things depending on whether the form is an MDI child or not, just interrogating the isChild property.

As for your second problem: do not use Application.CreateForm, but create your form yourself:

Here the two creations for modal and MDI:

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

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

I have translated this answer form an article on the site DelphiPraxis.

我偏爱纯白色 2024-08-12 15:01:43

最简单的方法是创建表单的一个简单子类,并

设置FormStyle = fsMDIChild

AND

Form.Visible = False

在属性检查器中 。这是经过尝试和测试的!

The simplest method is to create a trivial subclass of the form, and set

FormStyle = fsMDIChild

AND

Form.Visible = False

in the property inspector. This is tried and tested!

你怎么这么可爱啊 2024-08-12 15:01:43

至少对于 Delphi 2007 和 2009,创建不可见的 MDI 子窗体很容易。对于早期的 Delphi 版本(无法在属性检查器中将 Visible 设置为 False),您只需为 OnCreate 提供一个处理程序> 事件并访问类的受保护字段:

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

这将禁用 MDI 子项的自动显示。完成其他初始化后,您只需Show它或将Visible设置为True即可。

我不会尝试回答您有关模式 MDI 子表单的问题,因为这违反了 Windows 平台的约定。

At least for Delphi 2007 and 2009 creating the MDI child form invisible is easy. For the early Delphi versions (where it was impossible to set Visible to False in the property inspector) you just have to provide a handler for the OnCreate event and access a protected field of the class:

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

This will disable the automatic showing of the MDI child. After you are done with your other initialisations you can simply Show it or set Visible to True.

I will not try to answer your question about modal MDI child forms, as this violates the conventions of the Windows platform.

猫弦 2024-08-12 15:01:43

上面的答案实际上没有完成所需的工作。最佳答案也是错误的,原因如下:

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

No answers above actually does the job required. The best answer is wrong as well, because of following:

  • Opening the first form;
  • Maximize it;
  • Now say this form calls another form (mdi);
  • When it is constructed the same way you will get buggy layout... (it will mdi child, but not maximized, however the first will be still maximized). So a buggy state.

If you really need to decide in run-time whether it's a fsMDIChild or fsNormal you need to apply following approach.

  1. You have form which is stored as fsNormal in design (or vice-versa);
  2. Override the InitializeNewForm method;
  3. Set the value of FFormStyle to fsMDIChild (as shown below).

...

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文