0
votes

Today I have a question that is simple to ask, but not so simple to answer: is there a way to get a component by its tag?

I have a group of frames and in each of them the component I would like to focus is tagged as "1". The tagged component may be a TEdit, TMemo, TListBox, and so on.

From a frame controller, I would like to focus the control tagged as "1" in each frame according to the frame itself. Can I accomplish this task without knowing the component type or name?

2
Why is setting the tab order in your frame not sufficient? Does it not automatically focus the control with TabOrder set to 0?mghie
Iterate over the controls until you find the one with the desired property.David Heffernan

2 Answers

2
votes

Loop through the frame's Components[] list. Tag is a public property of TComponent.

var
  Comp: TComponent;
  I: Integer;
begin
  for i := 0 to frame.ComponentCount-1 do
  begin
    Comp := frame.Components[i];
    if Comp.Tag = 1 then
    begin
      (Comp as TWinControl).SetFocus;
      break;
    end;
  end;
end;

An alternative would be to define an interface that each frame implements, and have it simply return/manipulate the desired component directly without having to hunt for it:

type
  ITaggedComponent = interface
    ['{e5cfb88e-8c5d-4898-a008-742dd8d86698}']
    function GetTaggedComponent: TComponent;
    procedure FocusTaggedComponent;
    property TaggedComponent: TComponent read GetTaggedComponent;
  end;

type
  TFrame1 = class(TFrame, ITaggedComponent)
    Edit1: TEdit;
    ...
  public
    function GetTaggedComponent: TComponent;
    procedure FocusTaggedComponent;
  end;

  TFrame2 = class(TFrame, ITaggedComponent)
    Memo1: TMemo;
    ...
  public
    function GetTaggedComponent: TComponent;
    procedure FocusTaggedComponent;
  end;

  TFrame3 = class(TFrame, ITaggedComponent)
    ListBox1: TListBox;
    ...
  public
    function GetTaggedComponent: TComponent;
    procedure FocusTaggedComponent;
  end;

...

function TFrame1.GetTaggedComponent: TComponent;
begin
  Result := Edit1;
end;

procedure TFrame1.FocusTaggedComponent;
begin
  Edit1.SetFocus;
end;

function TFrame2.GetTaggedComponent: TComponent;
begin
  Result := Memo1;
end;

procedure TFrame2.FocusTaggedComponent;
begin
  Memo1.SetFocus;
end;

function TFrame3.GetTaggedComponent: TComponent;
begin
  Result := ListBox1;
end;

procedure TFrame3.FocusTaggedComponent;
begin
  ListBox1.SetFocus;
end;

...

Then you can do this:

var
  Intf: ITaggedComponent;
begin
  if Supports(frame, ITaggedComponent, Intf) then
    Intf.FocusTaggedComponent;
end;
0
votes

This should get your component - you can do what you want with it (set focus etc.) afterwards - assuming it is not nil

function TFrameController.GetMainControlForFrame( const pFrame : TFrame ) : TComponent;
begin
  for Result in pFrame do
  begin
    if Result.Tag = 1 then
    begin
      exit;
    end;
  end;
  // else
  Result := nil;
end;

I deliberately did not set the focus internally because you might want to get the same component for some other purpose.