Search code examples
windowsc++buildervclrad-studio

Can a secondary TForm notify the MainForm when it is closing?


I am using RAD Studio 10 working on a Windows VCL application. I have two Forms, Form1 (the MainForm in Unit1.cpp) and a secondary Form2 (in Unit2.cpp). I managed to embed Form2 inside of Form1. This is just a setup to illustrate the problem. My real project has multiple Forms.

When closing Form2, the VCL triggers the Form2::OnClose() event. Knowing that Form2 was created dynamically in Form1 (the MainForm), is there a Form1 event that will fire upon Form2 being closed? Or something inside Form1 to know that Form2 is closing?

  • I was thinking of customizing an event handler like OnChildFormClose but I couldn't make it.
  • I tried to wrap the code that I wanted to execute on Form1 when Form2 is closed in a public function and call it in the Form2::OnClose() event, and it worked to some extent, but it is not a good approach if you have multiple Forms.
//FROM THE unit1.cpp
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
//-----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//-----------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}
//-----------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
TForm2 *form2 = new TForm2(this);
form2->ManualDock(container);
form2->Show();
}
//FROM unit2.cpp
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
//-----------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//-----------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
    : TForm(Owner)
{
}
//-----------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
Close();
}
//-----------------------------------------------------------------------

Can I implement something like an OtherFormsonClose(*Sender) event in Form1 with a Sender that we can dynamically cast to check if it is Form2, or maybe I am wrong? I would appreciate some guidance.


Solution

  • You can declare a common event handler of type TCloseEvent, e.g. OtherFormClose(TObject *Sender, TCloseAction &Action); in the main form:

    private:    // User declarations
       void __fastcall TForm1::OtherFormClose(TObject *Sender, TCloseAction &Action);
    

    implementation

    void __fastcall TForm1::OtherFormClose(TObject *Sender, TCloseAction &Action)
    {
      Action = caFree;
      TForm2 *f2 = dynamic_cast<TForm2 *>(Sender);
      if (f2) {
      ShowMessage(String("Form2 closing")); //Do stuff
      }
    
    }
    

    (or use Sender to inspect which form)

    Then when you create other forms in code, e.g. Form2, you assign

      TForm2 *form2 = new TForm2(this);
      form2->OnClose = OtherFormClose;
      // etc