Delphi 从标签中获取组件

Delphi get component from its tag

今天有个问题问起来简单,回答起来却不简单:有没有办法通过标签获取组件?

我有一组框架,在每个框架中,我想要关注的组件都被标记为“1”。标记的组件可能是 TEdit、TMemo、TListBox 等。

在框架控制器中,我想根据框架本身在每个框架中聚焦标记为“1”的控件。 我可以在不知道组件类型或名称的情况下完成此任务吗?

这应该得到你的组件——之后你可以用它做你想做的事(设置焦点等)——假设它不是 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;

我故意没有在内部设置焦点,因为您可能想为其他目的获取相同的组件。

遍历框架的 Components[] 列表。 TagTComponent 的 public 属性。

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;

另一种方法是定义每个框架实现的 interface,并使其直接 return/manipulate 所需的组件而无需寻找它:

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;

...

那么你可以这样做:

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