Eros
Eros

Reputation: 469

Delphi get component from its tag

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?

Upvotes: 0

Views: 1954

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 595827

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;

Upvotes: 2

Dsm
Dsm

Reputation: 6013

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.

Upvotes: 0

Related Questions