Search code examples
delphidelphi-10.1-berlin

Set component focus with RTTI


Is it possible to reach any control Focus property through Rtti? What I want is to set its value to True if the control is Empty. Any help would be greatly appreciated.

procedure SetFirstEmptyCtrlFocused;

  function HasTextProp(aControl: TControl): Boolean;
  var
    Ctx: TRttiContext;
    Prop: TRttiProperty;
  begin
    Prop := lCtx.GetType(aControl.ClassType).GetProperty('Text');
    Result := (Prop <> nil) and (Prop.Visibility in [mvPublic, mvPublished]) 
      and (Prop.GetValue(aControl).ToString = '');
  end;

var
  ObjList: TObjectList<TControl>;
  objIdx: Integer;
  Ctrl: TControl;

begin
  ObjList := TObjectList<TControl>.Create;
  ObjList.Add(cxTextEdit1);
  ObjList.Add(cxDateEdit1);
  ObjList.Add(cxTextEdit2);

  for objIdx := 0 to lObjList.Count -1 do
  begin
    Ctrl := lObjList.Items[objIdx];

    if HasTextProp(lCtrl) then
    begin
      SetCtrlFocused //...??
      Break;
    end;
  end;   
end;  

Solution

  • Not every TControl can receive the focus, only TWinControl can. So instead of TControl use TWinControl and use its method SetFocus:

    procedure SetFirstEmptyWinCtrlFocused;
    
      function HasTextProp(aControl: TWinControl): Boolean;
      var
        Ctx: TRttiContext;
        Prop: TRttiProperty;
      begin
        Prop := Ctx.GetType(aControl.ClassType).GetProperty('Text');
        Result := (Prop <> nil) and (Prop.Visibility in [mvPublic, mvPublished]) 
          and (Prop.GetValue(aControl).ToString = '');
      end;
    
    var
      ObjList: TObjectList<TWinControl>;
      objIdx: Integer;
      Ctrl: TWinControl;
    
    begin
      ObjList := TObjectList<TWinControl>.Create;
      ObjList.Add(cxTextEdit1);
      ObjList.Add(cxDateEdit1);
      ObjList.Add(cxTextEdit2);
    
      for objIdx := 0 to lObjList.Count -1 do
      begin
        Ctrl := lObjList.Items[objIdx];
    
        if HasTextProp(Ctrl) then
        begin
          Ctrl.SetFocus;
          Break;
        end;
      end;   
    end;