Recent

Author Topic: OnEditingDone not triggered by Enter key-press.  (Read 13141 times)

RWC

  • Jr. Member
  • **
  • Posts: 92
OnEditingDone not triggered by Enter key-press.
« on: July 24, 2016, 05:21:56 pm »
I have several TEdit boxes for inputting & displaying Latitude, Longitude and Azimuth values. OnChange handles pasted input & runtime code changes. This works ok.

For typed input I use a shared OnKeyPress procedure to check for key validity (which is ok) and WAS using OnKeyUp & OnExit (in case the user forgot to press Enter) but was not getting Enter pressed entries.

Quote
From: http://forum.lazarus.freepascal.org/index.php/topic,32448.msg209295/topicseen.html#msg209295
Use the OnEditingDone event.
It is triggered when user presses Enter and when user leaves the control

After reading the above thread I changed my code to use OnEditingDone but it does not get triggered by the Enter key-press on this system nor my win7 Lazarus 1.6 FPC3.0 laptop setup.

Also I need to address the situation when the editbox is empty. i.e. if the user presses backspace before pasting it throws up a StrToFloat error. But I guess I can test for that in OnChange.

Any thoughts, comments or solutions to this Enter key issues will be much appreciated. Thank you, RWC.

The code below shows the shared edit validation procedure & the ViewPoint edit example.
Code: Pascal  [Select][+][-]
  1. //******************************************
  2. procedure TForm1.EditStepKeyPress(Sender: TObject; var Key: char);
  3. {Checks if the key pressed is valid and warns if not. Shared by all
  4. numeric editboxes.  Modified from: http://www.festra.com/eng/snip05.htm}
  5. begin
  6.   EdKeyPress:=True;
  7.   if not (Key in ['0'..'9','-','.',#13,#9,#8]) then
  8.   begin  //if not numbers 0 to 9, minus, period, ENTER, TAB or BACKSPACE key.
  9.     ShowMessage(Key +' Key is not Invalid');
  10.     Key := #0;
  11.   end
  12.   else if ((Key = '.') or (Key = '-')) and
  13.           (Pos(Key, (Sender as TEdit).Text) > 0) then
  14.   begin
  15.     ShowMessage('Cannot have two ' + Key + ' keys');
  16.     Key := #0;
  17.   end
  18.   else if (Key = '-') and ((Sender as TEdit).SelStart <> 0) then
  19.   begin
  20.     ShowMessage(Key + ' Must be at start of number');
  21.     Key := #0;
  22.   end
  23.   else if (Key = #13) and ((Sender as TEdit).SelStart = 0) then
  24.   begin
  25.     ShowMessage(' A number must be entered');
  26.     Key := #0;
  27.   end;
  28. end;
  29. //************************************************
  30. procedure TForm1.EditViewLatChange(Sender: TObject);
  31. begin
  32.   if not EdKeyPress then //it's not a keypress so...
  33.   begin    //...change was pasted or coded, update not done so do here.
  34.     ViewChanged:=True; //reset in chkbxGratShowClick
  35.     UpdateViewLat;       //update.
  36.     EdUpdateDone:=True;  //done.
  37.     Label11.Caption:='ViewLat paste or code'; //for testing
  38.   end;
  39. end;
  40. //***********************************************
  41. procedure TForm1.EditViewLatEditingDone(Sender: TObject);
  42. begin     //calls here if user presses Enter key or exits.
  43.   if EdKeyPress then  //validated
  44.   begin                
  45.    ViewChanged:=True; //made false in chkbxGratShowClick
  46.    UpdateViewLat;     //update mlat.
  47.    Label11.Caption:='ViewLat done by keys'; //for testing
  48.   end;
  49.   EdUpdateDone:=False;  //reset flags for later...
  50.   EdKeyPress:=False;    //...input.
  51. end;
  52. //**********************************************
  53. procedure TForm1.UpdateViewLat;
  54. begin
  55.   mlat:=StrToFloat(EditViewLat.Text); //mlat=typed/pasted lat.dec.degs.
  56.   dofpit:=-DegToRad(mlat); //update view display pitch offset
  57.   Label13.Caption:=FloatToStr(RadToDeg(dofpit));
  58.   ScrnPathLayer.FillTransparent; //View change so erase PathLayer.
  59.   chkbxGratShowClick(Self); //draws graticules if checked & calls Redraw:...
  60. end;
  61. //***********************************************
  62.  
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: OnEditingDone not triggered by Enter key-press.
« Reply #1 on: July 24, 2016, 11:39:32 pm »
OnEditingDone fires for me (Lazarus trunk, fpc 3.0.0, 32-bit, win7).

Mind you, some of your logic is plain wrong.
E.g. if I enter in a blank edit a '-', then select the text, press '-' again, it tells me I cannot have 2 '-' keys. This is wrong because the '-' i entered would overwrite the selected text anyway.
If I enter select all text, and the text is a number, and I press Enter-key, I get message 'A number must be entered'.

Also, IMO, showing a messagebox after each and every wrong input, forcing the user to press Enter or click OK will drive users nuts.
Just simply dismiss invalid input.
Use TextHint property of the TEdit to let the user kow he is supposed to enter a number in there.

Why do you try to re-invent the wheel?
If you want a control for iputting integers use TSpinEdit (or TSpinEditEx), or if your program is Windows only, use a TEdit and set NumbersOnly to True and let the OS handle it for you.

An alternative is TMaskEdit which will force the user to enter only digits and a leading + or minus if you set it up with the correct mask (something like '#99999').
It does not look very attractive, but it lets you control user-input in a very tight manner.

Bart

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #2 on: July 25, 2016, 07:47:58 pm »
@Bart: Criticism is sometime hard to take but your constructive criticism I welcome wholeheartedly. Thanks for your reply. :)
Quote
OnEditingDone fires for me (Lazarus trunk, fpc 3.0.0, 32-bit, win7).
You are correct. I’ve tried a new edit box without using (DelphiLand’s) OnKeyPress validation. Now the Enter key press DOES TRIGGER the OnEditingDone event handler. So that’s really good news. It also resolves a thought that was bothering me i.e. why would OnEditingDone be written if it did the same thing as OnExit (which it clearly does not).
Quote
Mind you, some of your logic is plain wrong.
E.g. if I enter in a blank edit a '-', then select the text, press '-' again, it tells me I cannot have 2 '-' keys. This is wrong because the '-' I entered would overwrite the selected text anyway.
I tried your pasting tests & got the same errors. I’ve only been pasting from other editboxes so haven’t encountered these errors. Thanks again for your more rigorous testing.
Quote
Also, IMO, showing a messagebox after each and every wrong input, forcing the user to press Enter or click OK will drive users nuts.
Just simply dismiss invalid input.
Use TextHint property of the TEdit to let the user know he is supposed to enter a number in there.
I agree – dismissing the invalid input is by far the better option. So that’s now three good reasons why I will be removing DelphiLand’s validation code completely since it is obviously flawed.

This is my first project using & learning Lazarus’ visual components so it’s all new & exiting for me. The easy use of hints is one of the many things I love about Lazarus.

I’m away for the next week so I’ll try your alternative suggestions when I get back.
Many many thanks Bart. All the best, RWC.
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #3 on: August 12, 2016, 06:15:27 pm »
Quote
If you want a control for iputting integers use TSpinEdit (or TSpinEditEx), or if your program is Windows only, use a TEdit and set NumbersOnly to True and let the OS handle it for you.
@Bart: I tried your alternative Tedit suggestions and also jujibo suggested by Molly in an earlier thread. They’re all good and work well for their own specific usage but none are quite what I want.
TfloatSpinEdit seems to be the closest option so far so maybe I can use parts of that code for TEdit.

I’m using your tip of ignoring bad input (i.e. no error messages) and I like the way that works but as I said before, if I use the OnKeyPress then the Enter key does not trigger the OnEditingDone (even if OnKeyPress contains just // ). If I then remove OnKeyPress completely, the OnEditingDone does respond to the Enter key?

Since most examples I’ve found use the OnKeyPress for checking valid input I’m using OnKeyDown (as a workaround) to catch the Enter key and redirect it to OnEditingDone where I’m using TryStrToFloat() as a final test? Comments welcome.

I did find one Delphi example that uses the Undo property of TCustomEdit in OnChange but it also needs ClearUndo which doesn’t seem to be available.

I have more than 20 Edit boxes so I need to use as much shared code as possible. Each box contains either 0..360, 0..+-180 or 0..+-0..90 with up to 8 decimal places of precision).

Any other comments, tips or solutions are much welcomed – Thanks again guys - RWC.
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

Bart

  • Hero Member
  • *****
  • Posts: 5275
    • Bart en Mariska's Webstek
Re: OnEditingDone not triggered by Enter key-press.
« Reply #4 on: August 12, 2016, 06:52:41 pm »

I’m using your tip of ignoring bad input (i.e. no error messages) and I like the way that works but as I said before, if I use the OnKeyPress then the Enter key does not trigger the OnEditingDone (even if OnKeyPress contains just // ). If I then remove OnKeyPress completely, the OnEditingDone does respond to the Enter key?

I cannot reproduce that.
1 form, 1 edit:

Code: [Select]
procedure TForm1.Edit1EditingDone(Sender: TObject);
begin
  writeln('Edit1EditingDone');
end;

procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: char);
begin
  writeln('Edit1KeyPress');
end;

I press Enter and get:

Code: [Select]
Edit1KeyPress
Edit1EditingDone

Bart

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #5 on: August 13, 2016, 06:09:36 pm »
Quote
I cannot reproduce that. 1 form, 1 edit:
@Bart: Thank you for your persistence & resolution. You have resolved a problem that’s been bugging me for months! I’ve always been tracing program flow using breakpoints but in this case it seems to have affected the flow leading to my confusion. The attached image shows my results i.e. without the OnKeyPress breakpoint it works correctly.

Also, I see you’re using ‘writeln’ in your test code and I’ve seen this used in lots of example code too but I had to use labels instead because Lazarus didn’t accept writeln. Please forgive me for my ignorance but are you using a different program for testing or am I selecting the wrong option from the Lazarus ‘New Project’ page (I’ve been using ‘Application’)?
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

wp

  • Hero Member
  • *****
  • Posts: 11854
Re: OnEditingDone not triggered by Enter key-press.
« Reply #6 on: August 13, 2016, 06:18:35 pm »
In a Windows GUI program, remove the checkmark in Project options / Compiler options / Config and Target / Win32 gui application. Then you can execute a WriteLn; the output will appear in a console window opened along with the main form.

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #7 on: August 13, 2016, 06:36:56 pm »
@wp: Thank you wp. WriteLn now works. You guys really are Hero Members.
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

ASerge

  • Hero Member
  • *****
  • Posts: 2222
Re: OnEditingDone not triggered by Enter key-press.
« Reply #8 on: August 13, 2016, 07:26:00 pm »
I’ve always been tracing program flow using breakpoints but in this case it seems to have affected the flow leading to my confusion. The attached image shows my results i.e. without the OnKeyPress breakpoint it works correctly.

In Windows order of event is: 1. WM_KEYDOWN, 2. WM_CHAR, 3. WM_KEYUP
OnKeyPress activate on 2, OnEditingDone on 3. If you use breakpoint at OnKeyPress, then WM_KEYUP goto debugger not to Edit, so no OnEditingDone.

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #9 on: August 16, 2016, 06:34:35 pm »
Quote
In Windows the order of events is…
@ Aserge: Thanks for that insight into Microsoft’s black box of tricks. The more we know the better. I did find that setting a breakpoint at Tedit’s OnKeyDown is ok & does go to OnKeyPress afterwards.

So far I’ve managed to reduce the procedures to 1 per edit box plus 2 shared by all edit boxes.
All edit boxes need to be set to a number at design time – see code below or attached source.

Again, any suggestions, comments, criticism, nit-picking, better solutions etc. most welcomed. Thanks a lot – RWC.
Code: Pascal  [Select][+][-]
  1. //use 1Form 2xTEdit.
  2. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: char);
  3. begin
  4.   if (Key in ['.', ',']) then Key := Decimalseparator;
  5.   if not (Key in ['0'..'9',DecimalSeparator,'-',#13,#9,#8]) then Key := #0
  6.   else if ((Key = Decimalseparator) or (Key = '-')) and
  7.         (Pos(Key, (Sender as TEdit).Text) > 0) then Key := #0
  8.   else if (Key = '-') and ((Sender as TEdit).SelStart <> 0) then Key := #0
  9. end;
  10.  
  11. procedure TForm1.Edit1Change(Sender: TObject);
  12. var sfloat: single;
  13. begin
  14.   if TEdit(Sender).Text = '-' then Exit;
  15.   if (TEdit(Sender).Text = '') then Exit;
  16.   if (TEdit(Sender).Text = Decimalseparator) then Exit
  17.   else if not TryStrToFloat(TEdit(Sender).Text,sfloat) then TEdit(Sender).Undo;
  18. end;
  19.  
  20. procedure TForm1.Edit1EditingDone(Sender: TObject);
  21. begin
  22.   if Edit1.Text = '' then Exit;
  23.   if Edit1.Text = '-' then Exit;
  24.   WriteLn('Latitude = '+ FloatToStrF(StrToFloat(Edit1.Text),ffGeneral,8,0));
  25. end;
  26.  
  27. procedure TForm1.Edit2EditingDone(Sender: TObject);
  28. begin
  29.   if Edit2.Text = '' then Exit;
  30.   if Edit2.Text = '-' then Exit;
  31.   WriteLn('Longitude = '+ FloatToStrF(StrToFloat(Edit2.Text),ffGeneral,8,0));
  32. end;
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: OnEditingDone not triggered by Enter key-press.
« Reply #10 on: August 16, 2016, 08:11:57 pm »
A slight optimisation of your second routine might be
Code: Pascal  [Select][+][-]
  1.   procedure TForm1.Edit1Change(Sender: TObject);
  2.   var
  3.     sfloat: single;
  4.     ed: TEdit absolute Sender;
  5.   begin
  6.     case Length(ed.Text) of
  7.       0: Exit;
  8.       1: if (ed.Text[1] in ['-', DecimalSeparator]) then Exit;
  9.     end;
  10.     if not TryStrToFloat(ed.Text, sfloat) then
  11.       ed.Undo;
  12.   end;      

Note that not all widgetsets support TEdit.Undo.

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #11 on: August 17, 2016, 06:02:30 pm »
Quote
A slight optimisation of your second routine might be
@ howardpc: Thank you that’s very interesting and works well. I’ve don’t fully understand it yet but that’s true of much of my code. Can ed also replace (Sender as TEdit) in the OnKeyPress routine?
Quote
Note that not all widgetsets support TEdit.Undo.
I would prefer cross platform code so I’ve replaced ed.Undo with ed.Text:='';  Exit;  Since the only way to enter a non numeric value is by pasting (or coding) it seems better to leave the edit box blank so if the user typed say 60. and then pasted the fractional part they may end up with something ridiculous like 60.bananas and may exit the box and not notice the Undo sets it to the previous incorrect 60.   

Many thanks for your valuable input. I hope many others with benefit from it too. All the best RWC.
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
Re: OnEditingDone not triggered by Enter key-press.
« Reply #12 on: August 17, 2016, 08:58:39 pm »
Can ed also replace (Sender as TEdit) in the OnKeyPress routine?

Yes, declaring ed as a variable "absolute Sender" is just an alternative to writing an explicit typecast of Sender. Pascal often provides such syntax alternatives, so choose the one you find most readable.

Quote
I would prefer cross platform code so I’ve replaced ed.Undo with ed.Text:='';  Exit;

You could also do something like the following, so if the user moves off the edit without giving valid input s/he gets (minimal) feedback. Note your Exit call is redundant.
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Edit1Change(Sender: TObject);
  2.     var
  3.       sfloat: single;
  4.       ed: TEdit absolute Sender;
  5.     begin
  6.       case Length(ed.Text) of
  7.         0: Exit;
  8.         1: if (ed.Text[1] in ['-', DecimalSeparator]) then Exit;
  9.       end;
  10.       if not TryStrToFloat(ed.Text, sfloat) then begin
  11.         ed.Text:='';
  12.         ed.TextHint:='invalid';
  13.       end;
  14.     end;    

RWC

  • Jr. Member
  • **
  • Posts: 92
Re: OnEditingDone not triggered by Enter key-press.
« Reply #13 on: August 19, 2016, 05:09:43 pm »
Quote
Yes, declaring ed as a variable… … Pascal often provides such syntax alternatives
@ howardpc: That’s a good clear overview - I’ll certainly be checking for other syntax alternatives.
 “(minimal) feedback” is good too, as mentioned by Bart earlier. I initially thought of using a beep sound but that seems to have cross platform complications too so I may settle for the Hint change or maybe change the Empty box to red until the next OnKeyPress.  Either way I’m really happy with the outcome & many thanks for everyone’s help – RWC.
LAZARUS  : Lazarus-1.4.2-fpc-2.6.4-win32. OS   : Windows Vista 32bit Home Premium SP2.
CPU  : Intel Core2 Quad CPU Q6600 2.4GHz. RAM : 3GB. PCIE : NVIDIA GeForce GT610. Audo : NVIDIA HD Audio.

 

TinyPortal © 2005-2018