Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2012-04

TBitBtn with Kid=bkClose and ModalResult

8 messages · 2 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Bart

A TBitBtn with Kind = bkClose will not set ModalResult of the ParentForm. As a result ShowModal on a form with such a TBitBtn will return mrCancel if this button is clicked, and not mrClose.

This is the piece of code that is responsable for this behaviour:

in lcl/include/bitbtn.inc

procedure TCustomBitBtn.Click;
var
  Form : TCustomForm;
begin
  if FKind = bkClose then begin
    Form := GetParentForm(Self);
    if Form  nil then begin
      Form.Close;
      exit;
    end;
  end;
  inherited Click;
end;

inherited click calls (in lcl/include/buttons.inc)

procedure TCustomButton.Click;
var
  Form : TCustomForm;
Begin
  if ModalResult  mrNone
  then begin
    Form := GetParentForm(Self);
    if Form  nil then Form.ModalResult := ModalResult;
  end;
  inherited Click;
end;

So if Kind bkClose then ModalResult of parentform is set, otherwise not. In TCustomForm.ShowModal, when ModalResult = 0 it will the set ModalResult to mrCancel.

Q: Is this by design?

Currently it makes MessageDlg() (more specific:
TPromptDialog.CreateMessageDialog) return wrong result if mbClose is in Buttons (and mbClose is clciked): see
http://bugs.freepascal.org/view.php?id=21801

Bart

Reply by email

Hans-Peter Diettrich
to Bart
A TBitBtn with Kind = bkClose will not set ModalResult of the ParentForm. As a result ShowModal on a form with such a TBitBtn will return mrCancel if this button is clicked, and not mrClose.

Only few button kinds have a defined ModalResult. It seems to be up to the developer to select the proper Kind, depending on the use in a modal or non-modal form.

Show quoted text 17 lines
This is the piece of code that is responsable for this behaviour: in lcl/include/bitbtn.inc procedure TCustomBitBtn.Click; var Form : TCustomForm; begin if FKind = bkClose then begin Form := GetParentForm(Self); if Form nil then begin Form.Close; exit; end; end; inherited Click; end;

I'd suggest that an explicitly set ModalResult should be checked, before actions are invoked that are incompatible with modal forms. But Delphi also checks Kind *before* ModalResult, so this is a compatibility issue.

DoDi

Reply by email

Bart
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote
I'd suggest that an explicitly set ModalResult should be checked, before actions are invoked that are incompatible with modal forms. But Delphi also checks Kind *before* ModalResult, so this is a compatibility issue.

If you have a recent Delphi version can you test what the ModalResult is when you close a Modal form by clicking on a TBitButton with Kind = bkClose and Modalresult = mrClose (just put a TBitBtn on this form and in OI set Kind = bkClose) ?

(My Delphi (3) does have bkClose as a valid choice for TBitBtnKind, but it does not have mrClose as a valid choice for TModalResult, so it obviously will not return mrClose.)

Bart

Reply by email

Hans-Peter Diettrich
to Bart
Show quoted text 10 lines
On 4/21/12, Hans-Peter Diettrich wrote: > I'd suggest that an explicitly set ModalResult should be checked, before > actions are invoked that are incompatible with modal forms. But Delphi > also checks Kind *before* ModalResult, so this is a compatibility issue. If you have a recent Delphi version can you test what the ModalResult is when you close a Modal form by clicking on a TBitButton with Kind = bkClose and Modalresult = mrClose (just put a TBitBtn on this form and in OI set Kind = bkClose) ?

It will be the default result, when the ModalResult property is never changed in code. I.e. the same as when the dialog is closed using ALT-F4 or the border icons. I assume that ModalResult is initialized during ShowModal, else the result from the *previous* ShowModal would be returned.

From Delphi help:
mrNone 0 None. Used as a default value before the user exits.

(My Delphi (3) does have bkClose as a valid choice for TBitBtnKind, but it does not have mrClose as a valid choice for TModalResult, so it obviously will not return mrClose.)

From D7 help:

>

TModalResult represents the value returned by a modal dialog. An application can use any integer value as a modal result value. <<

I.e. one can define mrClose and assign it to the close button's ModalResult. But this won't help, when the button logic doesn't use the ModalResult when Kind=bkClose.

DoDi

Reply by email

Bart
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 9 lines
From D7 help: >> TModalResult represents the value returned by a modal dialog. An application can use any integer value as a modal result value. << I.e. one can define mrClose and assign it to the close button's ModalResult. But this won't help, when the button logic doesn't use the ModalResult when Kind=bkClose.

Lazarus treats this as a special case (bkClose), but does Delhi also?

If you have a modern Delphi (as in higher then D3) could you please test this. Put a TBitBtn on a form.
Set Kind = bkClose (in OI)
Set Modalresult = mrClose (in OI)
ShowModal this form
Click on this TBitBtn
What is the value Modalresult: mrCancel or mrClose?

Bart

Reply by email

Bart
to Bart
Bart wrote 11 lines
If you have a modern Delphi (as in higher then D3) could you please test this. Put a TBitBtn on a form. Set Kind = bkClose (in OI) Set Modalresult = mrClose (in OI) ShowModal this form Click on this TBitBtn What is the value Modalresult: mrCancel or mrClose? Bart

I had someone with Delphi XE test this for me. Delphi returns mrClose in this case, so I think this is LCL bug.

Bart

Reply by email

Hans-Peter Diettrich
to Bart
Show quoted text 16 lines
On 4/22/12, Bart wrote: > If you have a modern Delphi (as in higher then D3) could you please test > this. > Put a TBitBtn on a form. > Set Kind = bkClose (in OI) > Set Modalresult = mrClose (in OI) > ShowModal this form > Click on this TBitBtn > What is the value Modalresult: mrCancel or mrClose? > > Bart > I had someone with Delphi XE test this for me. Delphi returns mrClose in this case, so I think this is LCL bug.

Here it returns mrCancel by default. When the ModalResult of the button is specified, this value is returned. On close with "X" the result is always mrCancel.

Not worth to mimic this inconsistent behaviour in the LCL, IMO. Older Delphi code also will be fooled when mrClose is returned, which has been introduced only after D7.

DoDi

Reply by email

Bart
to Hans-Peter Diettrich
Hans-Peter Diettrich wrote 7 lines
Here it returns mrCancel by default. When the ModalResult of the button is specified, this value is returned. On close with "X" the result is always mrCancel. Not worth to mimic this inconsistent behaviour in the LCL, IMO. Older Delphi code also will be fooled when mrClose is returned, which has been introduced only after D7.

Not sure what your last statement actually means:
a) LCL should return mrClose if TBitBtn.Modalresult = mrClose, even if TBitBtn.Kind = bkClose
b) LCL should not return mrClose, since D7 (and earlier) does not support that.

?

Bart

Reply by email