【问题标题】:How to detect whether a TWinControl has a FONT property?如何检测 TWinControl 是否具有 FONT 属性?
【发布时间】:2020-06-08 08:12:33
【问题描述】:

我需要更改通过容器控件的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 的类型?

【问题讨论】:

  • 为什么要这样做?如果您有一个带有很多子控件的窗口控件,您可以通过简单地更改父控件的字体来更改所有子控件的字体。默认情况下这是有效的,因为默认情况下ParentFont 是True。否则,如果你知道你只有少量可能的类,你可以做一个简单无聊的if Controls[i] is TEdit then TEdit(Controls[i]).Font.Name := 'Comic Sans MS' else if Controls[i] is TButton then...
  • 具体原因这里解释的太复杂了,我不能用ParentFont。
  • 你错了。您可以使用 ParentFont
  • 如果已分配(GetPropInfo(ContainerControl.Controls[i], 'font')) 然后
  • 请记住,某些控件可能有超过 1 个字体属性。当然,如前所述,有主要的Font,但也可能有不同的元素需要单独的字体属性。比如TChromeTabs这个第三方控件就有很多。

标签: delphi rtti delphi-10.3-rio


【解决方案1】:

所有可视控件都有一个Font 属性,但它在TControl 层是protected,并非所有派生控件都将其提升为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;

【讨论】:

    【解决方案2】:

    每个 TControl 都有一个 Font 属性,它只是受到保护。所以你可以使用the usual cast trick:

    type
      TControlAccess = class(TControl);
    
    TControlAccess(MyControl).Font.Size := 10;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-18
      • 2019-04-30
      • 2021-03-12
      • 1970-01-01
      相关资源
      最近更新 更多