delphimdimdichildmdiparent

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


I have 2 MDI ChildForms and the Child1 has a TButton to open the Child2. I do not have any issue opening it at the same time disable the TButton to prevent Child2 from recreating again using TButton.

Now, the challenge comes when I want the TButton of Child1 back to "enabled" when I closed the Child2.

I am getting access error when doing these code:

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

I understand there is somehow a different approach when dealing with MDI. I figured it out when I did the code for disabling the TButton during opening at runtime below:

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

But to enable it back when the Child2 form is closed is a challenge.

I tried to create a procedure in the MainForm (Owner) to trigger the enable of TButton in the Child1:

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

and called at runtime during OnClose of Child2:

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

I am new to MDI and I need to understand how accessing components works particular this simple case. I will appreciate any help here.


Solution

  • I would take a different approach - assign the 2nd child's OnClose event dynamically when the 1st child creates the 2nd child. Don't have the 2nd child try to find and access the 1st child directly:

    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;
    

    Just make sure the 2nd child is always closed before the 1st child is freed, otherwise you will have trouble. If you need to, you can solve that like this:

    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;