Reputation: 256581
If the user clicks X on my main form, i want the form to hide, rather than close. This sounds like a job for the OnClose form event:
Use OnClose to perform special processing when the form closes. The OnClose event specifies which event handler to call when a form is about to close. The handler specified by OnClose might, for example, test to make sure all fields in a data-entry form have valid contents before allowing the form to close.
A form is closed by the Close method or when the user chooses Close from the form's system menu.
The TCloseEvent type points to a method that handles the closing of a form. The value of the Action parameter determines if the form actually closes. These are the possible values of Action:
- caNone: The form is not allowed to close, so nothing happens.
- caHide: The form is not closed, but just hidden. Your application can still access a hidden form.
- caFree: The form is closed and all allocated memory for the form is freed.
- caMinimize: The form is minimized, rather than closed. This is the default action for MDI child forms.
Which i test in an empty application with one form:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action := caHide;
end;
So now when i click X, (rather than hiding) the form closes and the application terminates:
...which sounds like a job for the OnClose event...
Vcl.Forms.pas
procedure TCustomForm.Close;
var
CloseAction: TCloseAction;
begin
if fsModal in FFormState then
ModalResult := mrCancel
else if CloseQuery then
begin
if FormStyle = fsMDIChild then
if biMinimize in BorderIcons then
CloseAction := caMinimize
else
CloseAction := caNone
else
CloseAction := caHide;
DoClose(CloseAction);
if CloseAction <> caNone then
begin
if Application.MainForm = Self then //Borland doesn't hate developers; it just hates me
Application.Terminate
else if CloseAction = caHide then
Hide
else if CloseAction = caMinimize then
WindowState := wsMinimized
else
Release;
end;
end;
end;
Upvotes: 3
Views: 2528
Reputation: 321
Try the OnCloseQuery
event. Hide the form and set CanClose
to False. You should be good.
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
Hide;
CanClose := False;
end;
Upvotes: 9
Reputation: 595319
When the user closes a window, it receives a WM_CLOSE
message, which triggers TForm
to call its Close()
method on itself. Calling Close()
on the project's MainForm
always terminates the app, as this is hard-coded behavior in TCustomForm.Close()
:
procedure TCustomForm.Close;
var
CloseAction: TCloseAction;
begin
if fsModal in FFormState then
ModalResult := mrCancel
else
if CloseQuery then
begin
if FormStyle = fsMDIChild then
if biMinimize in BorderIcons then
CloseAction := caMinimize else
CloseAction := caNone
else
CloseAction := caHide;
DoClose(CloseAction);
if CloseAction <> caNone then
if Application.MainForm = Self then Application.Terminate // <-- HERE
else if CloseAction = caHide then Hide
else if CloseAction = caMinimize then WindowState := wsMinimized
else Release;
end;
end;
Only secondary TForm
objects respect the output of the OnClose
handler.
To do what you are asking for, you can either:
handle WM_CLOSE
directly and skip Close()
.
private
procedure WMClose(var Message: TMessage); message WM_CLOSE;
procedure TForm1.WMClose(var Message: TMessage);
begin
Hide;
// DO NOT call inherited ...
end;
have your MainForm's OnClose
handler call Hide()
directly and return caNone
:
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Hide;
Action := caNone;
end;
Upvotes: 11