Recent

Author Topic: how not to execute onexit  (Read 4214 times)

rcmz

  • Full Member
  • ***
  • Posts: 137
Re: how not to execute onexit
« Reply #15 on: July 24, 2024, 07:07:33 pm »
Thx,

Nice observation, where can I put the code ?

The code uses the info from tedit to search in a db and extract a description so it populates other tedit an tlabel components.

TIA
Ramiro

wp

  • Hero Member
  • *****
  • Posts: 12459
Re: how not to execute onexit
« Reply #16 on: July 24, 2024, 08:11:01 pm »
Maybe add a OnMouseDown handler to the Cancel button which removes the OnExit handler from the Edit controls (Edit.OnExit := nil)? I think OnMouseDown should fire before the Edit.OnExit.

alpine

  • Hero Member
  • *****
  • Posts: 1297
Re: how not to execute onexit
« Reply #17 on: July 24, 2024, 10:37:06 pm »
Thx,

Nice observation, where can I put the code ?

The code uses the info from tedit to search in a db and extract a description so it populates other tedit an tlabel components.

TIA
Ramiro
You can simply raise a flag in TEdit.OnChange and then check it into the TEdit.OnExit if your intention is not to do the search when the form is about to close.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: how not to execute onexit
« Reply #18 on: July 25, 2024, 08:41:37 am »
Thx,

Nice observation, where can I put the code ?

The code uses the info from tedit to search in a db and extract a description so it populates other tedit an tlabel components.

TIA
Ramiro
You can simply raise a flag in TEdit.OnChange and then check it into the TEdit.OnExit if your intention is not to do the search when the form is about to close.
Thought about that, too, but don't think it would work.

@TS
Thx,

Nice observation, where can I put the code ?

The code uses the info from tedit to search in a db and extract a description so it populates other tedit an tlabel components.

TIA
Ramiro
Depends what other controls are on your Form.
Let's say, you have 2 (or more) TEdits.
You enter your stuff in TEdit1, and when you Tab/click forward to the next TEdit, it grabs something from a DB, and shows it in another TEdit or TLabel (or whatever).
If that's the case, then i would put the "Grab from DB"-Code not in the OnExit of TEdit1, but in the OnEnter (Or whatever the event's name) of TEdit2.
That way, if you are in TEdit1, but then click on your Button, that "Grab from DB"-Code is not executed, since that code resides in TEdit2, which never gets entered.

But that's just a guess now, since we don'T know how your form is designed
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

alpine

  • Hero Member
  • *****
  • Posts: 1297
Re: how not to execute onexit
« Reply #19 on: July 25, 2024, 12:24:57 pm »
Thx,

Nice observation, where can I put the code ?

The code uses the info from tedit to search in a db and extract a description so it populates other tedit an tlabel components.

TIA
Ramiro
You can simply raise a flag in TEdit.OnChange and then check it into the TEdit.OnExit if your intention is not to do the search when the form is about to close.
Thought about that, too, but don't think it would work.
On a second thought - yes, it won't - but at least will skip the processing when not modified.
What I would do is to put a button for manual refresh and enable it according to a combined "dirty" flag.
As a last resort, if the refresh must be performed automatically, I would put it on a 2-3 seconds TTimer.OnTimer. Thus it wont be performed so often (multiple filter fields can be edited meanwhile) and it can be skipped on close.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

rcmz

  • Full Member
  • ***
  • Posts: 137
Re: how not to execute onexit
« Reply #20 on: July 25, 2024, 06:50:14 pm »
hi,

the option suggested from wp, using the mousedown event, did not work. I will keep trying.

TIA
Ramiro

alpine

  • Hero Member
  • *****
  • Posts: 1297
Re: how not to execute onexit
« Reply #21 on: July 25, 2024, 07:21:25 pm »
Include this at the beginning of the TEdit.OnExit event:
Code: Pascal  [Select][+][-]
  1.   if Screen.ActiveControl = CancelButton then
  2.     Exit;
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zoran

  • Hero Member
  • *****
  • Posts: 1882
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: how not to execute onexit
« Reply #22 on: July 26, 2024, 09:19:31 am »
Include this at the beginning of the TEdit.OnExit event:
Code: Pascal  [Select][+][-]
  1.   if Screen.ActiveControl = CancelButton then
  2.     Exit;

Testing where the focus went is not enough; focus might have jumped to CancelButton without the button being clicked.

alpine

  • Hero Member
  • *****
  • Posts: 1297
Re: how not to execute onexit
« Reply #23 on: July 26, 2024, 10:20:26 am »
Quote
Testing where the focus went is not enough; focus might have jumped to CancelButton without the button being clicked.
So playing with the focus is generally incorrect then.
I've suggested  TEdit.OnChange  and delayed refresh (OnEditingDone is focus related).
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: how not to execute onexit
« Reply #24 on: July 26, 2024, 12:44:16 pm »
So playing with the focus is generally incorrect then.
Have to disagree.
In Post 18 lower half i actually described an alternative
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

bpranoto

  • Full Member
  • ***
  • Posts: 183
Re: how not to execute onexit
« Reply #25 on: July 26, 2024, 01:04:56 pm »
The code uses the info from tedit to search in a db and extract a description so it populates other tedit an tlabel components.

If I were you, I won't bother.  Even if the Cancel Button clicked, it is correct to extract  the info from the db and reflect it in the other TEdit or TLabel.




alpine

  • Hero Member
  • *****
  • Posts: 1297
Re: how not to execute onexit
« Reply #26 on: July 26, 2024, 01:25:03 pm »
So playing with the focus is generally incorrect then.
Have to disagree.
In Post 18 lower half i actually described an alternative
Me too in #21. Zoran said the button may got the focus but the form may still be open - should the db data get retrieved then?
It depends. We all speculate on limited information from OP.
"I'm sorry Dave, I'm afraid I can't do that."
—HAL 9000

Zoran

  • Hero Member
  • *****
  • Posts: 1882
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: how not to execute onexit
« Reply #27 on: July 26, 2024, 02:11:41 pm »
So playing with the focus is generally incorrect then.
Have to disagree.
In Post 18 lower half i actually described an alternative
Me too in #21. Zoran said the button may got the focus but the form may still be open - should the db data get retrieved then?
It depends. We all speculate on limited information from OP.

Might be limited information, but I am almost sure that it is the following:
As I understand he wants to skip updating fields from database (might be an expensive operation) when the form is about to close.
Edit boxes are filled from database in EditBox.OnExit event (OnEditingDone can be used instead, but it would not help as it is triggered even earlier than OnExit). If an Edit has focus, this event fires when a user clicks on a button which closes the form. In that particular case it would be reasonable to skip OnExit.

It seems that inside OnExit you cannot tell if the form is about to close (checking Screen.ActiveControl is not good enough, as I said before).
Form.OnCloseQuery, Form.OnClose, Button.OnClick are all triggered too late to set Edit.OnExit to nil. Even Button.OnMouseDown, which Werner suggested to try, seems to happen too late.

As a workaround I can only suggest to try with calling Application.QueueAsyncCall inside OnExit (or OnEditingDone); Form.OnCloseQuery should call Application.RemoveAsyncCalls(Self). Not very elegant in my opinion, but should work.

Something like this (not tested):
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     Button1: TButton;
  13.     Edit1: TEdit;
  14.     Edit2: TEdit;
  15.     procedure Button1Click(Sender: TObject);
  16.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  17.     procedure FormCreate(Sender: TObject);
  18.   private
  19.     AboutToClose: Boolean;
  20.  
  21.     procedure EditsEditingDone(Sender: TObject);
  22.     procedure UpdateFromDb(Data: PtrInt);
  23.   public
  24.  
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. procedure TForm1.Button1Click(Sender: TObject);
  37. begin
  38.   { these two lines are also in FormCloseQuery, so probably not needed here. I put them anyway }
  39.   AboutToClose := True;
  40.   Application.RemoveAsyncCalls(Self);
  41.  
  42.   Close;
  43. end;
  44.  
  45. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  46. begin
  47.   AboutToClose := True;
  48.   Application.RemoveAsyncCalls(Self);
  49. end;
  50.  
  51. procedure TForm1.FormCreate(Sender: TObject);
  52. begin
  53.   AboutToClose := False;
  54.   Edit1.OnEditingDone := @EditsEditingDone;
  55.   Edit2.OnEditingDone := @EditsEditingDone;
  56. end;
  57.  
  58. procedure TForm1.EditsEditingDone(Sender: TObject);
  59. begin
  60.   if not AboutToClose then
  61.     Application.QueueAsyncCall(@UpdateFromDb, 0);
  62. end;
  63.  
  64. procedure TForm1.UpdateFromDb(Data: PtrInt);
  65. begin
  66.   // code for updating edit boxes from database
  67. end;
  68.  
  69. end.
  70.  
« Last Edit: July 26, 2024, 02:16:39 pm by Zoran »

Joanna from IRC

  • Hero Member
  • *****
  • Posts: 1208
Re: how not to execute onexit
« Reply #28 on: July 26, 2024, 03:18:59 pm »
There is also checking if the edit was modified inside the change event, if it wasn’t modified the oneditingdone event should be ignored.
✨ 🙋🏻‍♀️ More Pascal enthusiasts are needed on IRC .. https://libera.chat/guides/ IRC.LIBERA.CHAT  Ports [6667 plaintext ] or [6697 secure] channel #fpc  #pascal Please private Message me if you have any questions or need assistance. 💁🏻‍♀️

Zvoni

  • Hero Member
  • *****
  • Posts: 2738
Re: how not to execute onexit
« Reply #29 on: July 26, 2024, 03:41:41 pm »
So playing with the focus is generally incorrect then.
Have to disagree.
In Post 18 lower half i actually described an alternative
Me too in #21. Zoran said the button may got the focus but the form may still be open - should the db data get retrieved then?
It depends. We all speculate on limited information from OP.

Might be limited information, but I am almost sure that it is the following:
As I understand he wants to skip updating fields from database (might be an expensive operation) when the form is about to close.
Edit boxes are filled from database in EditBox.OnExit event (OnEditingDone can be used instead, but it would not help as it is triggered even earlier than OnExit). If an Edit has focus, this event fires when a user clicks on a button which closes the form. In that particular case it would be reasonable to skip OnExit.

It seems that inside OnExit you cannot tell if the form is about to close (checking Screen.ActiveControl is not good enough, as I said before).
Form.OnCloseQuery, Form.OnClose, Button.OnClick are all triggered too late to set Edit.OnExit to nil. Even Button.OnMouseDown, which Werner suggested to try, seems to happen too late.

As a workaround I can only suggest to try with calling Application.QueueAsyncCall inside OnExit (or OnEditingDone); Form.OnCloseQuery should call Application.RemoveAsyncCalls(Self). Not very elegant in my opinion, but should work.

Something like this (not tested):
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     Button1: TButton;
  13.     Edit1: TEdit;
  14.     Edit2: TEdit;
  15.     procedure Button1Click(Sender: TObject);
  16.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  17.     procedure FormCreate(Sender: TObject);
  18.   private
  19.     AboutToClose: Boolean;
  20.  
  21.     procedure EditsEditingDone(Sender: TObject);
  22.     procedure UpdateFromDb(Data: PtrInt);
  23.   public
  24.  
  25.   end;
  26.  
  27. var
  28.   Form1: TForm1;
  29.  
  30. implementation
  31.  
  32. {$R *.lfm}
  33.  
  34. { TForm1 }
  35.  
  36. procedure TForm1.Button1Click(Sender: TObject);
  37. begin
  38.   { these two lines are also in FormCloseQuery, so probably not needed here. I put them anyway }
  39.   AboutToClose := True;
  40.   Application.RemoveAsyncCalls(Self);
  41.  
  42.   Close;
  43. end;
  44.  
  45. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  46. begin
  47.   AboutToClose := True;
  48.   Application.RemoveAsyncCalls(Self);
  49. end;
  50.  
  51. procedure TForm1.FormCreate(Sender: TObject);
  52. begin
  53.   AboutToClose := False;
  54.   Edit1.OnEditingDone := @EditsEditingDone;
  55.   Edit2.OnEditingDone := @EditsEditingDone;
  56. end;
  57.  
  58. procedure TForm1.EditsEditingDone(Sender: TObject);
  59. begin
  60.   if not AboutToClose then
  61.     Application.QueueAsyncCall(@UpdateFromDb, 0);
  62. end;
  63.  
  64. procedure TForm1.UpdateFromDb(Data: PtrInt);
  65. begin
  66.   // code for updating edit boxes from database
  67. end;
  68.  
  69. end.
  70.  
Or move the code from OnExit to the OnEnter event of the following control. Ofc must have sanity checks
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

 

TinyPortal © 2005-2018