I am using C++Builder with a VCL Forms Application. I am trying to close a VCL Form that is docked on a TPageControl. My Close button is on a toolbar on the program's main form. My approach to do this is the three steps below: I can step through all this code but when it is done nothing happens, the form is not closed. What am I doing wrong here?
.
void __fastcall TAboutForm::FormClick(TObject *Sender)
{
MainForm1->LastSelectedFormName = AboutForm->Name;
}
void __fastcall TMainForm1::CloseButtonClick(TObject *Sender)
{ //Identify The Form to Delete by Name
bool q=true;
UnicodeString FormName="";
int cnt = Screen->FormCount;
for(int i=0; i<cnt; i++ )
{
TForm* form = Screen->Forms[i];
FormName = form->Name;
if(CompareText(FormName, LastSelectedFormName)==0){
form->OnCloseQuery(form, q); //close this form
break;
}
}
}
void __fastcall TAboutForm::FormCloseQuery(TObject *Sender, bool &CanClose)
{
int Code = Application->MessageBox(L"Close Form", L"Close Form", MB_YESNO|MB_ICONINFORMATION);
if(Code ==IDYES){
TCloseAction Action = caFree;
FormClose(Sender, Action);
}
}
void __fastcall TAboutForm::FormClose(TObject *Sender, TCloseAction &Action)
{
Action = caFree;
}
Below is an edit after reading the answer from Spektre
Calling form->OnClose(form, MyAction); will not trigger the FormCloseQuery event. I have to call FormCloseQuery manually. The only way I could get the docked form to close is by adding, delete Sender; to the FormCloseQuery.
This does not look like a correct solution. I am very surprised Embarcadero does not have a recommended way to close a docked form. This seems like a very common action. I read the doc-wiki and can not find any solution to close a docked form.
void __fastcall TMainForm1::CloseButtonClick(TObject *Sender)
{ //Identify The Form to Delete by Name
bool MyCanClose=true;
UnicodeString FormName="";
TCloseAction MyAction = caFree;
int cnt = Screen->FormCount;
for(int i=0; i<cnt; i++ )
{
TForm* form = Screen->Forms[i];
FormName = form->Name;
if(CompareText(FormName, LastSelectedFormName)==0){
// form->OnClose(form, MyAction);
form->OnCloseQuery(form, MyCanClose);
break;
}
}
}
void __fastcall TAboutForm::FormCloseQuery(TObject *Sender, bool &CanClose)
{
int Code = Application->MessageBox(L"Close Form", L"Close Form", MB_YESNO|MB_ICONINFORMATION);
if(Code ==IDYES){
delete Sender;
Sender = NULL;
}
}
You need to call Form->Close()
instead of the Form->OnCloseQuerty()
but leave the event code as is (as you want the close confirmation dialog)
Form->OnCloseQuerty()
is called by VCL you should not call it on yourself !!! It has different meaning it does not force the Form
to close but it can reject the Close
event if CanClose
is set to false
.
Form->Close()
This one force the Form
to Close. But first the VCL will call the Form->OnCloseQuerty()
and according to its result it either ignore the Close or proceed with it.
There are also another alternatives to do what you want. In case you just want to hide your Form you can also set its Visible
property to false instead. And when want to use it again just use Show()
or even ShowModal()
or set its Visible
to True
again (it depends on if your App is MDI or not).
Another way is to create and delete the Form dynamically using new,delete
. The delete of the form is forcing the Form
to close regardless of Form->OnCloseQuery()
result.
I sometimes combine these two methods ... And set the Visible=false
and CanClose=false
in OnCloseQuery()
and before the App destruction delete
all dynamical Forms
...