delphifiremonkeytabstop

FireMonkey control with TabOrder = 0 is not focused at runtime


I have 3 custom tRectangle on a form. When creating the custom tRectangle, I set CanFocus = True;, so the tRectangle can be focused. On FormCreate event, I set the TabOrder to 0 to the first tRectangle, to 1 to the second tRectangle and to 2 to the third tRectangle.

When running the application, the first tRectangle, since it's TabOrder is 0, should get the focus, but it does not.

Also, when tabbing, the second control gets focus, then the third control and at this point the focus gets stuck. Now, if tabbing with the Shift key pressed, the second control gets focus, until it reaches the first control, and again the focus gets stuck.

I appreciate if anyone can tell me why the control with TabOrder 0 is not focused at runtime and why tabbing is not acting in a circular way.

Follows code:

unit frmMyRect;
interface
uses FMX.Controls, FMX.Controls.Presentation, FMX.Forms, FMX.Layouts, 
     FMX.Objects, FMXFMX.StdCtrls, FMX.Types,System.Classes, System.UITypes;
type
  tfrmMyRect =  class (tForm)
     procedure FormCreate (Sender: tObject);
  end;
  tMyRect = class (tRectangle)
    fMyRectLabel : tLabel;
    constructor Create (aOwner : tComponent);
    procedure MyRectClick (Sender: tObject);
    procedure MyRectEnter (Sender: tObject);
    procedure MyRectExit  (Sender: tObject);
    function GetText : string;
    procedure SetText (const aText: string);
    published
      property Text : string read GetText write SetText;
  end;
var formMyRect: tfrmMyRect;
implementation
{$R *.fmx}
var MyRect1 : tMyRect;
    MyRect2 : tMyRect;
    MyRect3 : tMyRect;
procedure tformMyRect.FormCreate (Sender: tObject);
begin
  MyRect1 := tMyRect.Create (Self);
  MyRect1.Parent := frmMyRect;
  MyRect1.TabOrder := 0;
  MyRect1.Text := 'MyRect&1';
  MyRect2 := tMyRect.Create (Self);
  MyRect2.Parent := frmMyRect;
  MyRect2.TabOrder := 1;
  MyRect2.Text := 'MyRect&2';
  MyRect3 := tMyRect.Create (Self);
  MyRect3.Parent := frmMyRect;
  MyRect3.TabOrder := 2;
  MyRect3.Text := 'MyRect&3';
end; { FormCreate }
constructor tMyRect.Create (aOwner: tComponent);
begin
   inherited;
  CanFocus   :=  True;
  Height     :=   23;
  OnClick    :=  MyRectClick;
  OnEnter    :=  MyRectEnter;
  OnExit     :=  MyRectExit;
  TabStop    :=  True;
  Width      :=   80;
  fMyRectLabel := tLabel.Create (Self);
    with fMyRectLabel do begin
           Align          := tAlignLayout.Center;
           FocusControl   :=  Self;
           HitTest        :=  False;
           Parent         :=  Self;
           StyledSettings := [];
           TabStop        :=  False;
            with TextSettings do begin
                 FontColor  := TAlphaColorRec.Blue;
                 WordWrap   :=  False;
                 Font.Style := [TFontStyle.fsBold];
            end;
    end;
  end; { Create }
  procedure ctMyRect.MyRectClick (Sender: tObject);
  begin
    Fill.Color := TAlphaColorRec.Aqua;
  end;
  procedure ctMyRect.MyRectEnter (Sender: TObject);
  begin
    Fill.Color := TAlphaColorRec.Aqua;
  end;
  procedure ctMyRect.MyRectExit (Sender: TObject);
  begin
    Fill.Color := TAlphaColorRec.Beige;
  end;
  end.

Solution

  • 1. Control with TabOrder = 0 is not focused when form first appears

    I can confirm this with your code and also with e.g. TEdit controls. Consider two edit controls on a form. When added to the form in the designer, the first one added got TabOrder = 0. When the form is first shown, neither has focus. After a Tab entry, the first created receives the focus.

    From help for FMX.Controls.TControl.TabOrder:

    TabOrder is the order in which child controls are visited when the user presses the TAB key. The control with the TabOrder value of 0 is the control that has the focus when the form first appears.

    The second sentence is not correct. But the control with TabOrder = 0 will be the first to receive focus when user hits Tab key.

    To assure that a specific control has focus already when the containing form appears, set:

    Focused := MyRect1;
    

    or, maybe better:

    MyRect1.SetFocus;
    

    in the forms OnCreate() event.


    2. Tabbing is not acting in a circular way

    After trying your code, I still cannot reproduce the problem you claim. Maybe you are just misjudging what appears to you.

    Because of this line at the beginning of constructor tMyRect.Create():

    Align      := tAlignLayout.Center;
    

    all rects are on top of each other in the center of the form, IOW you can only see the top one. (Focused controls are not automagically brought to the front) Remove that line and place the rects appart (position.X and position.Y) so you can see which one is currently focused.

    The line FocusControl := Self; seems misplaced (in XE7 at least), so I outcommented it.

    TAB through the tMyRect controls works exactly as expected, in the order:

    MyRect1 - MyRect2 - MyRect3 - Myrect1 ...

    and Shift-TAB in the opposite order.