Search code examples
delphifiremonkeydelphi-xe5

Delphi firemonkey tabstop problems in a tabcontrol


I'm writing a Firemonkey HD program in Delphi XE5 Update 2 for windows platform. I have a tabcontrol with a tabitem on the form and some edit boxes in the tabitem. I have the taborder set accordingly (0,1,2,..), when I enter Edit1 and hit tab, Edit1 looses focus but Edit2 does not get focus.

I tried putting the editboxes on the main form and in a panel and there they work correctly, When I'm in edit1 and hit tab it goes to edit2 and so on, but on a tabitem in a tabcontrol it does not.

Does anyone know of a work around for this or maybe a setting that I missed?

Thanks for any help


Solution

  • I had the same issue in my application, so I wrote a workaround:

    http://andydunkel.net/delphi/coding/2013/11/23/firemonkey_xe_4_taborder_workaround.html

    I am using a FormHelper class, the key down method of the Form (reacts to the Tab Key) and the help context property of the controls.

    First I was setting the help context, you can use the tag for example too. But I am already using the tag property for something else:

    enter image description here

    unit FormHelper;
    
    interface
    
    type
      TFormHelper = class helper for TForm
        procedure DoTabHandlingXE(comp : TForm; tabOrder : Integer);
      end;
    
    implementation
    
    //Workaround for Tab-Bug in Firemonkey
    procedure TFormHelper.DoTabHandlingXE(comp: TForm; tabOrder : Integer);
    var
      i, c :integer;
      current : TComponent;
      currentNext : integer;
      focus : TStyledControl;
    begin
      c := Self.ComponentCount - 1;
      currentNext := 9999;
      focus := nil;
    
      for i := 0 to c do begin
          current := Self.Components[i];
          if (current is TStyledControl) then begin
              if ((current as TStyledControl).HelpContext < currentNext) and 
              ((current as TStyledControl).HelpContext > tabOrder) then begin
                currentNext := (current as TStyledControl).HelpContext;
              end;
          end;
      end;  
    
      for i := 0 to c do begin
          current := Self.Components[i];
          if (current is TStyledControl) then begin
            if (currentNext = (current as TStyledControl).HelpContext) then begin
              focus := (current as TStyledControl);
            end;
          end;
      end;
    
      if focus <> nil then begin
        focus.SetFocus;
    end;
    end;
    end.
    

    Of course the code does nothing to far, since the method is not called yet. So the next step is to implement the KeyDown event in the form:

    procedure TfrmEinzField.KeyDown(var Key: Word; var KeyChar: Char;
      Shift: TShiftState);
    var
      control : TStyledControl;
    begin
      if Key = vkTab then
      begin
        //custom handling
        if (Self.GetFocused is TStyledControl) then begin
          control := (Self.GetFocused as TStyledControl);
          DoTabHandlingXE(Self, control.HelpContext);
        end;
      end else
        inherited; //do default handling
    end;
    

    In the code, we get the currently focused control. Then we call the method we wrote before with the current Form variable and the controls HelpContext value. With that workaround the tab key is now working as expected, jumping to the next control.

    More details are in the blog post.