在关闭另一个 MDI 子窗体时启用一个 MDI 子窗体的 TButton

Enable a TButton of an MDI ChildForm upon closing of another MDI ChildForm

我有 2 个 MDI ChildForms,Child1 有一个 TButton 来打开 Child2。我打开它没有任何问题,同时禁用 TButton 以防止 Child2 使用 TButton 再次重新创建。

现在,挑战来了,当我关闭 Child2 时,我希望 Child1 的 TButton 回到 "enabled"。

我在执行这些代码时遇到访问错误:

procedure TfrmChild2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  child1_u.frmChild1.btnOpenChild2Form.Enabled := True;
  Action := caFree;
end;

我知道在处理 MDI 时有一种不同的方法。当我在下面的运行时打开期间执行禁用 TButton 的代码时,我想通了:

procedure TfrmMain.btnOpenChild2(Sender: TObject);
begin
  TfrmChild2.Create(frmMain);
  btnOpenChild2.Enabled := False;
end;

但是要在 Child2 窗体关闭时重新启用它是一个挑战。

我试图在 MainForm(所有者)中创建一个过程来触发 Child1 中 TButton 的启用:

procedure TfrmMain.EnableButtonAtChild1();
begin
  child1_u.frmChild1.btnOpenChild1Form.Enabled := True;  
end;

并在 Child2 的 OnClose 期间在运行时调用:

procedure TfrmChild2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  EnableButtonAtChild1();
end;

我是 MDI 的新手,我需要了解访问组件的工作原理,尤其是在这个简单的案例中。我将不胜感激。

我会采取不同的方法 - 在第一个 child 创建第二个 child 时动态分配第二个 child 的 OnClose 事件。不要让第二个 child 尝试直接查找和访问第一个 child:

procedure TfrmChild1.btnOpenChild2FormClick(Sender: TObject);
var
  child: TfrmChild2;
begin
  child := TfrmChild2.Create(Application.MainForm);
  child.OnClose := Child2Closed;
  btnOpenChild2Form.Enabled := False;
end;

procedure TfrmChild1.Child2Closed(Sender: TObject; var Action: TCloseAction);
begin
  btnOpenChild2.Enabled := True;
  Action := caFree;
end;

只要确保第二个 child 总是在第一个 child 被释放之前关闭,否则你会遇到麻烦。如果需要,您可以这样解决:

procedure TfrmChild1.FormDestroy(Sender: TObject);
var
  I: Integer;
  child: TForm;
  event: TCloseEvent;
begin
  for I := 0 to Application.MainForm.MDIChildCount-1 do
  begin
    child := Application.MainForm.MDIChildren[I];
    event := child.OnClose;
    if Assigned(event) and (TMethod(event).Data = Self) then
      child.OnClose := nil;
  end;
end;