Recent

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

Aidex

  • Jr. Member
  • **
  • Posts: 82
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: 12464
You must set the ModalResult of the Form to prevent the form from closing.

Aidex

  • Jr. Member
  • **
  • Posts: 82
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: 12464
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 »

Aidex

  • Jr. Member
  • **
  • Posts: 82
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: 12464
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.

Aidex

  • Jr. Member
  • **
  • Posts: 82
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: 12464
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.

Aidex

  • Jr. Member
  • **
  • Posts: 82
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: 4144
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: 2337
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: 292
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.  

AgriMensor

  • New Member
  • *
  • Posts: 41
I can't find where the bkAbort and other bk constants are defined, so the unit won't compile when I rry to set .Kind programmatically. Can you please point me to where they are? Thx!

wp

  • Hero Member
  • *****
  • Posts: 12464
I can't find where the bkAbort and other bk constants are defined, so the unit won't compile when I rry to set .Kind programmatically. Can you please point me to where they are? Thx!
Unit "buttons" (but this should be added to "uses" automatically when you drop a TBitBtn on the form).

AgriMensor

  • New Member
  • *
  • Posts: 41
I can't find where the bkAbort and other bk constants are defined, so the unit won't compile when I rry to set .Kind programmatically. Can you please point me to where they are? Thx!
Unit "buttons" (but this should be added to "uses" automatically when you drop a TBitBtn on the form).
Great, wp, thanks very much! It now works fine. It wasn't automatically dropped into the Uses section. Either that, or I've inadvertently deleted it, but I don't think so!

 

TinyPortal © 2005-2018