Recent

Author Topic: [SOLVED] need very early Button-Event or very late ComboBox-Event  (Read 1701 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 739
[SOLVED] need very early Button-Event or very late ComboBox-Event
« on: September 18, 2021, 05:48:24 pm »
The problem in my "big program" can be reduced to a small demo which has only 1 TComboBox and 1 TButton:
 - The ComboBox is editable and has an OnEditingDone-Event, where the user input is checked and an error dialog is displayed if neccessary.
 - One Button is to Close the program, the other Button is to set special values into the ComboBox.

The problem is:
If Button "Close" is pressed and the content of the ComboBox is not valid, an error dialog is displayed, which makes no sense. Same thing, when the other Button is pressed, when the content of the ComboBox is not valid: because a new value is set by the Button, it makes no sense to display before an error dialog for an outdated value.

My idea is:
to have a global boolean variable like "check_it" which tells, whether the OnEditingDone-Event shall check or not. This var would normally be true and a very early Button-Event could set it to false. But I didn't find such an event. "OnClick" comes too late (comes after "OnEditingDone" has done it's check).

My questions are:
 - is there a very early TButton-Event for this purpose?
 - or is there a much later TComboBox-Event then OnEditingDone? "OnExit" comes too early too.
 - if no, how can I solve that problem?

I hope for a solution not to complicate, because my "real world program" has a lot more of Buttons and other Controls.
I use Lazarus 2.0.6 with FPC 3.0.4. Thanks a lot in advance.
« Last Edit: September 19, 2021, 04:14:26 pm by Hartmut »

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: need very early Button-Event or very late ComboBox-Event
« Reply #1 on: September 18, 2021, 06:53:19 pm »
OnEditingDone is too late for error checking, it fires when another control has the focus. The correct event would be something like OnValidate which fires before the combobox loses focus.

An option could be to use the OnExit event. It comes even later, after OnEditingDone, but now you already know which control will be focused (ActiveControl). So, you could move the validity check to this event, but skip the check when the "Close" button is the ActiveControl. This observation is for Windows, I cannot say whether the same observation can be madde for other OSs as well.

Hartmut

  • Hero Member
  • *****
  • Posts: 739
Re: need very early Button-Event or very late ComboBox-Event
« Reply #2 on: September 18, 2021, 07:25:43 pm »
Hello wp again! Thanks for your post.

OnValidate seems not to exist in Lazarus 2.0.6. Updating my project at this time is not an option.

OnExit sounds very interesting because of 'ActiveControl' (again learned something new from you and will investigate it tomorrow) but I found 2 disadvantages: it is not fired when you edit the ComboBox and press ENTER and it is not fired as long as you only select something from the DropDown-List of the ComboBox. Maybe I must live with that, if no other idea comes.

wp

  • Hero Member
  • *****
  • Posts: 11830
Re: need very early Button-Event or very late ComboBox-Event
« Reply #3 on: September 18, 2021, 07:55:59 pm »
OnValidate seems not to exist in Lazarus 2.0.6. Updating my project at this time is not an option.
My sentence was not complete. I wanted to say: OnValidate would be the correct event, but it does not exist.

OnExit [...] is not fired when you edit the ComboBox and press ENTER and it is not fired as long as you only select something from the DropDown-List of the ComboBox.
Catch OnKeyDown and check for VK_RETURN - this will allow you to validate after typing

And: Validation after selecting an item from the dropdown list does not appear to be necessary to me because the list should contain only valid items anyway. But of course, if you must do it, you can use the event OnCloseUp which fires when the dropdown closes which happens when a new item has been selected or the user has cancelled the selection by pressing ESC or clicking somewhere else - in the latter case, still a valid item should be selected.

So, in total not very elegant, but feasible...


jamie

  • Hero Member
  • *****
  • Posts: 6077
Re: need very early Button-Event or very late ComboBox-Event
« Reply #4 on: September 18, 2021, 08:50:25 pm »
Hmm, maybe I don't understand but you seem to want to limit the users input to which is in the list?

Code: Pascal  [Select][+][-]
  1. procedure TForm1.ComboBox1Change(Sender: TObject);
  2. var
  3.   L:Integer;
  4. begin
  5.   With TComboBox(Sender) do
  6.    Begin
  7.      If Caption <> '' Then
  8.       Begin
  9.         For L := 0 To Items.Count-1 do
  10.          If LeftStr(Items[L],Length(Caption))= Caption Then Exit;
  11.         Beep; //No matches;
  12.       end;
  13.    end;
  14. end;                    
  15.  
The only true wisdom is knowing you know nothing

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: need very early Button-Event or very late ComboBox-Event
« Reply #5 on: September 18, 2021, 09:13:06 pm »
You could do the check as you do at the moment (OnEditingDone).

If there is an error, do Application.QueueAsync(MyErrMethod).
The queued method, is only executed when all other events have been done. So the buttons can remove the async queued method.

There is a method to remove them by object/instance, so you need to create an object for that. You can use the Form, as long as the form has no other async events.

Of course if you do "save and exit" the async method may not be run at all. But you could have a flag, and run it in the appropriate button.

Hartmut

  • Hero Member
  • *****
  • Posts: 739
Re: need very early Button-Event or very late ComboBox-Event
« Reply #6 on: September 19, 2021, 09:52:35 am »
Catch OnKeyDown and check for VK_RETURN - this will allow you to validate after typing
Yes, that should work.

Quote
And: Validation after selecting an item from the dropdown list does not appear to be necessary to me because the list should contain only valid items anyway. But of course, if you must do it, you can use the event OnCloseUp which fires when the dropdown closes which happens when a new item has been selected...
I need not only to do some error checks with new values, I need also do a couple of "actions" after a new value was entered or selected.
I checked OnCloseUp-Event and it does what I need.

So I can replace OnEditingDone by a combination of OnKeyDown + OnCloseUp + OnExit which can check 'ActiveControl' to determine the new control (which works in Linux too, I checked this).

Quote
So, in total not very elegant, but feasible...
Yes, but thanks a lot for this possible solution. Before I implement it, I will see what Martin_fr means.



Hmm, maybe I don't understand but you seem to want to limit the users input to which is in the list?
No, this was not my question. Thanks.

Hartmut

  • Hero Member
  • *****
  • Posts: 739
Re: need very early Button-Event or very late ComboBox-Event
« Reply #7 on: September 19, 2021, 10:30:09 am »
You could do the check as you do at the moment (OnEditingDone).

If there is an error, do Application.QueueAsync(MyErrMethod).
The queued method, is only executed when all other events have been done. So the buttons can remove the async queued method.

There is a method to remove them by object/instance, so you need to create an object for that. You can use the Form, as long as the form has no other async events.

Of course if you do "save and exit" the async method may not be run at all. But you could have a flag, and run it in the appropriate button.

That sounds very elegant, thanks a lot, but I did not understand the details how to implement it.
Should/must 'MyErrMethod' be a method of 'Form1'?
From my understanding the buttons do not need to "remove" the async queued method. Can I use a boolean variable 'check_it' instead to disable the error checks by the buttons?
Is it correct, that the async queued method is only fired once?

The Documentation of Application.QueueAsyncCall() says that it needs a method of:
Code: Pascal  [Select][+][-]
  1. type TDataEvent = procedure(Data: PtrInt) of object;

I tried to declare
Code: Pascal  [Select][+][-]
  1. type TForm1 = class(TForm)
  2. ...
  3.    procedure MyErrMethod(Data: PtrInt) of object;
  4.  
but the compiler says 'Fatal: Syntax error, ";" expected but "OF" found'

Need more help please, this things are completely new to me, Thanks.

Bart

  • Hero Member
  • *****
  • Posts: 5265
    • Bart en Mariska's Webstek
Re: need very early Button-Event or very late ComboBox-Event
« Reply #8 on: September 19, 2021, 02:41:27 pm »
The "of object"  is not needed (and wrong, as the compiler tells you).
Methods of a class by nature have the signature ... "of Object" already.

Bart

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 9754
  • Debugger - SynEdit - and more
    • wiki
Re: need very early Button-Event or very late ComboBox-Event
« Reply #9 on: September 19, 2021, 02:53:54 pm »
On the Application object you have
Code: Pascal  [Select][+][-]
  1.     procedure QueueAsyncCall(const AMethod: TDataEvent; Data: PtrInt);
  2.     procedure RemoveAsyncCalls(const AnObject: TObject);
  3.  

You can add your new method to TForm.
Code: Pascal  [Select][+][-]
  1. type TForm1 = class(TForm)
  2. ...
  3.    procedure MyErrMethod(Data: PtrInt)

And then
Code: Pascal  [Select][+][-]
  1.   Application.QueueAsyncCall(@MyErrMethod);

You can store a flag somewhere, and check the flag in "MyErrMethod".
You can remove the method
Code: Pascal  [Select][+][-]
  1. Application.RemoveAsyncCalls(self); // when self=form1

As you see, if form1 would have other asyncs queued, then they would also be removed.

Also note: In Form1.Destroy you should call the RemoveAsyncCalls. Otherwise your method could be called with a destroyed Form1 in self. OUch.

You can queue multiple times, leading to multiple invocations. To avoid that, you can keep a flag if you already queued.
Then you end up with
Code: Pascal  [Select][+][-]
  1. type TForm1(TForm)
  2.   private
  3.     FHasQueuedErrMethod: Boolean;
  4.     FHasError: Boolean;
  5.     procedure SetHasError;
  6.     procedure ClearHasError;
  7.  
The procedures "SetHasError" queues an Async, but only if none is pending.
ClearHasError will remove the async method.

Hartmut

  • Hero Member
  • *****
  • Posts: 739
Re: need very early Button-Event or very late ComboBox-Event
« Reply #10 on: September 19, 2021, 04:13:44 pm »
Thank you very much to Bart and Martin_fr for that helpful and very detailed informations. With this it was easy for me to get a 1st try to run and it does exactly what I needed :-))

Thanks again to all who helped me.

 

TinyPortal © 2005-2018