Search code examples
delphifiremonkey

Delphi FMX set focus to a particular control so the cursor appears


I created a test new FMX project. Added a TabControl to it. Used the context menu to add 3 tabsheets. To the 3rd tabsheet, added a TEdit. Added a OnChangeEvent handler to the tabcontrol. Coded it as follows:

procedure TForm1.TabControl1Change(Sender: TObject);
begin
  if TabControl1.ActiveTab = TabItem3 then
  begin
    self.ActiveControl := Edit1;
    self.Focused := Edit1;
    Edit1.SetFocus;
  end;
end;

As you can see, I tried various combinations based on my previous VCL experience. The input/cursor focus does not change to the Edit1 by code. Of course, at runtime on Win32, if I click on the edit1, the focus rectangle (I'm using a style) now shows as does the cursor. (as expected) On Android. The VK only comes up when I shift the focus myself.

Is there way to do this programmatically so the user can just start typing? (without having to shift the focus to the TEdit themselves).


Solution

  • The firemonkey framework prohibits change of focus in some events.

    In order to change the focus, send a delayed message to the form.

    This could be done with an anonymous thread:

    procedure TForm1.TabControl1Change(Sender: TObject);
    begin
      if TabControl1.ActiveTab = TabItem3 then
      begin
        TThread.CreateAnonymousThread(
          procedure
          begin
            TThread.Synchronize( nil,
              procedure
              begin
                Edit1.SetFocus;
              end
            );
          end
        ).Start;
      end;
    end;
    

    To make it more general, use a dedicated procedure:

    procedure DelayedSetFocus(control : TControl);
    begin
      TThread.CreateAnonymousThread(
        procedure
        begin
          TThread.Synchronize( nil,
             procedure
             begin
               control.SetFocus;
             end
          );
        end
      ).Start;
    end;