Jump to content

Delphi 11.1 FMX TEdit struggles

Recommended Posts

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);
  s : string;
  i1, i2, i3, i4, imax : integer;
  iTotal : integer;
  savePos : integer;
  saveEvent : TNotifyEvent;
  saveEvent := TEdit (sender).OnChangeTracking;
  TEdit (sender).OnChangeTracking := nil;

    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
    if iTotal > 0 then
        // 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
          TEdit (sender).CaretPosition := savePos;


        TEdit (sender).SelStart := TEdit (sender).CaretPosition;
        TEdit (sender).SelLength := 0;


    TEdit (sender).OnChangeTracking := saveEvent;

Share this post

Link to post

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
      if (HackEditSaveCaretPos >= 0) then
        HackEdit.CaretPosition := HackEditSaveCaretPos

      HackEdit.SelStart := HackEdit.CaretPosition;
      HackEdit.SelLength := 0;

All works as it should now.

Share this post

Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now