KMarb 5 Posted September 17, 2022 I have a TEdit for user to enter a job number. Job numbers vary in format, but one format is yy-xxxx, where yy is the year, so 22-1437 is a valid job number. The popup keyboard on android sometimes does not list a minus sign (dash) when entering numbers. In the past I programmed the edit control to take any of these characters (comma, *, #, space) and to convert them to a dash on the fly. Ideally I could do this in KeyUp or KeyDown or KeyPress (if it existed in FMX but it does not), and just swap characters. I haven't been able to make that work for some reason, so I'm resorting to the OnChangeTracking event. My code is below. IT is way longer than I would need if I could intercept and change character in KeyUp or KeyDown. The problem I have is, say user types 22#. # is replaced with -, so TEdit now holds 22- and the caret is flashing after the -. When user types the next number, it appears at the START of the edit field, not after the - as expected. On screen the caret is where it should be right up until I type the number after the -. This is one of those that I've spent a couple hours on and it should be trivial. Maybe it is. Please advise. procedure TfrmMain.edtJobChangeTracking(Sender: TObject); var s : string; i1, i2, i3, i4, imax : integer; iTotal : integer; savePos : integer; saveEvent : TNotifyEvent; begin saveEvent := TEdit (sender).OnChangeTracking; TEdit (sender).OnChangeTracking := nil; try savePos := TEdit (sender).CaretPosition; s := TEdit (sender).Text; i1 := s.IndexOf (' '); i2 := s.IndexOf ('#'); i3 := s.IndexOf ('*'); i4 := s.IndexOf (','); iTotal := i1 + i2 + i3 + i4 + 4; // -1 from indexOf means not found if i1 >= 0 then s := s.Replace (' ', '-', [rfReplaceAll]); if i2 >= 0 then s := s.Replace ('#', '-', [rfReplaceAll]); if i3 >= 0 then s := s.Replace ('*', '-', [rfReplaceAll]); if i4 >= 0 then s := s.Replace (',', '-', [rfReplaceAll]); if iTotal > 0 then TEdit (sender).Text := s; RunRefSearch; // this is the query in database to see if we found a match finally if iTotal > 0 then begin // 9/17/22 - cannot get this to work right... // user types 22#... display shows 22- which is what I want // but next character appears at START of edit field, not after the - if (savePos < 0) or (savePos = s.Length) then TEdit (sender).GoToTextEnd else TEdit (sender).CaretPosition := savePos; TEdit (sender).SelStart := TEdit (sender).CaretPosition; TEdit (sender).SelLength := 0; end; TEdit (sender).OnChangeTracking := saveEvent; end; end; Share this post Link to post
KMarb 5 Posted September 17, 2022 I've solved my problem by adding a timer that I call in the finally block that does the things listed in the finally. It runs with a 50ms so I don't notice any delays with the screen. This required me to save the current editor and caret position in form variables, and the code is much uglier than I'd like, but I will take working over pretty any time. first two lines of ChangeTracking event: HackEdit := TEdit (sender); // HackEdit is a form var of TEdit HackEditSaveCaretPos := HackEdit.CaretPosition; In the finally I have this now: TEdit (sender).OnChangeTracking := saveEvent; if iTotal > 0 then tmrHackEdit.Enabled := true; and the timer does this: tmrHackEdit.Enabled := false; if assigned (HackEdit) then begin if (HackEditSaveCaretPos >= 0) then HackEdit.CaretPosition := HackEditSaveCaretPos else HackEdit.GoToTextEnd; HackEdit.SelStart := HackEdit.CaretPosition; HackEdit.SelLength := 0; end; All works as it should now. Share this post Link to post