首页 > 解决方案 > 如何检测 TWinControl 是否具有 FONT 属性?

问题描述

我需要更改通过Controls容器控件的属性收集的控件的 FONT 属性:

for i := 0 to ContainerControl.ControlCount - 1 do
begin  
  ContainerControl.Controls[i].Font.Size := 8;  // error  
end;

为此,我需要将类型转换ContainerControl.Controls[i]为具有 FONT 属性的 TWinControl 类。有这样的课吗?或者如何检测特定的 TWinControl 是否具有 FONT 属性?或者我怎么能将特定的 TWincontrol 类型转换为特定的其他 TWinControl 的类型?

标签: delphirttidelphi-10.3-rio

解决方案


所有可视控件都有一个Font属性,但它protected位于TControl图层上,并非所有派生控件都将其提升为published. 如果您只对已发布 Font的控件感兴趣,则必须使用 RTTI 对其进行测试,例如:

uses
  ..., TypInfo;

var
  Ctrl: TControl;
  i: Integer;
begin
  for i := 0 to ContainerControl.ControlCount - 1 do
  begin  
    Ctrl := ContainerControl.Controls[i];
    if IsPublishedProp(Ctrl, 'Font') then
      TFont(GetObjectProp(Ctrl, 'Font', TFont)).Size := 8;
  end;
end;

或者:

uses
  ..., TypInfo;

var
  Ctrl: TControl;
  Prop: PPropInfo;
  i: Integer;
begin
  for i := 0 to ContainerControl.ControlCount - 1 do
  begin  
    Ctrl := ContainerControl.Controls[i];
    Prop := GetPropInfo(Ctrl, 'Font', [tkClass]);
    if Prop <> nil then
      TFont(GetObjectProp(Ctrl, Prop, TFont)).Size := 8;
  end;
end;

或者,仅在 Delphi 2010 及更高版本中:

uses
  ..., System.Rtti;

var
  Ctrl: TControl;
  Ctx: TRttiContext;
  Prop: TRttiProperty;
  i: Integer;
begin
  Ctx := TRttiContext.Create;
  try
    for i := 0 to ContainerControl.ControlCount - 1 do
    begin  
      Ctrl := ContainerControl.Controls[i];
      Prop := Ctx.GetType(Ctrl.ClassType).GetProperty('Font');
      if (Prop <> nil) and (Prop.Visibility = TMemberVisibility.mvPublished) then
        TFont(Prop.GetValue(Ctrl).AsObject).Size := 8;
    end;
  finally
    Ctx.Free;
  end;
end;

推荐阅读