Recent

Author Topic: BitBtn bkClose closes window even though ModalResult is mrNone. Bug or feature?  (Read 2269 times)

Aidex

  • New Member
  • *
  • Posts: 28
Hello!
I've placed a TBitBtn on a form, choose bkClose kind, but want to handle OnClick myself, so I've set the button's modalresult to mrNone.
I hoped mrNone would prevent automatically closing the form, but the window closes before I can handle the button's OnClick event.
As I understood mrNone, it shouldn't close a form.
« Last Edit: November 12, 2017, 11:55:32 am by Aidex »

wp

  • Hero Member
  • *****
  • Posts: 6471
You must set the ModalResult of the Form to prevent the form from closing.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Aidex

  • New Member
  • *
  • Posts: 28
Form's ModalResult is mrNone! (default)
There's no change when I set Form.ModalResult:=mrNone at runtime or in BitBtn.OnClick() event.
The form will be closed anyway!
« Last Edit: November 12, 2017, 11:51:11 am by Aidex »

wp

  • Hero Member
  • *****
  • Posts: 6471
It *is* working - I do this all the time for error checking before a form can close. See attached demo.

Maybe my description was too short: you must use the OnClick event of the form to set its ModalResult to mrNone in order to prevent closing of the form. Having clicked on the OKButton has changed the form's Modalresult to the ModalResult of the button. Therefore, the form closes when the OnClick handler exits. Setting the form's ModalResult back to mrNone prevents closing the form.
« Last Edit: November 12, 2017, 11:59:59 am by wp »
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Aidex

  • New Member
  • *
  • Posts: 28
Oh yes, in your example it's working - because the button is not on the main form.
But in my program the button is on Form1 and it always closes the program.  :(
I can reproduce it in your example program, too, when I copy the button from Form2 to Form1
(also after setting button's ModalResult to mrNone)

wp

  • Hero Member
  • *****
  • Posts: 6471
I forgot: Another, more general way to prevent a form from closing is the OnCloseQuery event in which you simply set the parameter CanClose to false if the form should remain open. This technique is used primarily for the MainForm. In case of secondary forms it has problems, though, because the form even cannot be closed by the system close button ("x") which is generally very confusing to a user.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Aidex

  • New Member
  • *
  • Posts: 28
Yes, I see, but in my program the "Close" BitBtn is on a panel - to hide the panel - not to close a form.
So I want to prohibit the button to close a form in any case, because its function refers to a panel, not to a form.

Of course, I can use another button that won't close a form, but I think it's a bug that the bkClose BitBtn on Form1 always closes the program, altough it is to send mrNone as ModalResult.
« Last Edit: November 12, 2017, 12:36:31 pm by Aidex »

wp

  • Hero Member
  • *****
  • Posts: 6471
I think it's a bug that the bkClose BitBtn on Form1 always closes the program, altough it is to send mrNone as ModalResult.
Certainly not. That's the way buttons are designed. A modal form executes a continuous loop which exits when its ModalResult is different from mrNone. The click on a button transfers its ModalResult to the Modalresult of the form, and therefore closes the form if the button's Modalresult is not mrNone. If the form is the MainForm then the program quits.

If you want the button to only hide a panel, then the button's ModalResult must be mrNone. But: in my tests it turned out that the form may close if the button's Kind is still mkClose; only after switching it back to mkCustom the form stayed open. (This step preserves the button's Close icon). Then, in the button's OnClick you can hide the panel.
Lazarus trunk / fpc 3.0.4 / all 32-bit on Win-10

Aidex

  • New Member
  • *
  • Posts: 28
Yes, that's all right and clear to me, but shouldn't the button behave on Form1 in the same way you're using it on Form2 ?!
So I'm still thinking that it's a bug to ignore its mrNone setting (property in IDE) of the bkClose button.
Should I report it as a bug?

howardpc

  • Hero Member
  • *****
  • Posts: 3202
No, the "Close" in TBitBtn's Kind property value bkClose  refers specifically to the closing of the button's containing form.
You cannot use a TBitBtn of Kind bkClose for closing panels etc. without working around the tightly integrated ModalResult and form-closing modality that is built in to TBitBtn in the LCL (if you don't want the button also to close the form). Far better to use a non-bkClose button for closing panels etc. when the 'problem' of the form's ModalResult changing behind your back is simply not present.

But a possible work-around would be as follows:

Code: Pascal  [Select]
  1. type
  2.  
  3.   TForm1 = class(TForm)
  4.     PanelCloseBitBtn: TBitBtn;
  5.     Panel1: TPanel;
  6.     procedure PanelCloseBitBtnMouseDown(Sender: TObject; Button: TMouseButton;
  7.       Shift: TShiftState; X, Y: Integer);
  8.     procedure FormCloseQuery(Sender: TObject; var CanClose: boolean);
  9.   private
  10.     PanelClosed: Boolean;
  11.   end;
  12.  
  13. var
  14.   Form1: TForm1;
  15.  
  16. implementation
  17.  
  18. procedure TForm1.PanelCloseBitBtnMouseDown(Sender: TObject; Button: TMouseButton;
  19.   Shift: TShiftState; X, Y: Integer);
  20. begin
  21.   if Sender is TBitBtn then begin
  22.     PanelCloseBitBtn.Enabled:=False;
  23.     PanelClosed:=True;
  24.     Panel1.Visible:=False;
  25.   end;
  26. end;
  27.  
  28. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: boolean);
  29. begin
  30.   CanClose:=not PanelCloseBitBtn.Enabled or not PanelClosed;
  31.   PanelClosed:=False;
  32. end;
« Last Edit: November 12, 2017, 01:20:58 pm by howardpc »

ASerge

  • Hero Member
  • *****
  • Posts: 1422
Hello!
I hoped mrNone would prevent automatically closing the form, but the window closes before I can handle the button's OnClick event.
As I understood mrNone, it shouldn't close a form.
Widely known, but not documented feature. When Kind = bkClose, always closed the parent form. If you like the "Close" picture, put the style in bkCustom, in this case the special behavior disappears, but the picture remains.

FTurtle

  • Sr. Member
  • ****
  • Posts: 260
Widely known, but not documented feature. When Kind = bkClose, always closed the parent form. If you like the "Close" picture, put the style in bkCustom, in this case the special behavior disappears, but the picture remains.

Code:
Code: Pascal  [Select]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   BitBtn1.Kind:=bkClose;
  4.   BitBtn1.Kind:=bkCustom;
  5.   BitBtn1.ModalResult:=mrNone;
  6. end;
  7.