24

是否有一种快速有效的方法来应用要在项目中使用的全局字体?

我的意思是我想设置一个特定的字体名称,我的项目中的所有控件都将使用,例如TButtonTEditTLabel

通常,为 Form 而不是特定控件设置 Font 会将该 Form 上的所有控件更改为指定的 Font。

但是,这有一个小问题,如果您手动更改了特定控件上的字体,那么通过表单设置字体将不再更新以前手动更改的那些控件。

理念一

我正在考虑使用 For 循环并遍历表单上的每个组件并以这种方式设置字体,例如:

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  with TForm(Self) do
  begin
    for i := 0 to ComponentCount - 1 do
    begin
      if Components[i] is TButton then
      begin
        TButton(Components[i]).Font.Name  := 'MS Sans Serif';
        TButton(Components[i]).Font.Size  := 8;
        TButton(Components[i]).Font.Style := [fsBold];
      end;

      if Components[i] is TLabel then
      begin
        TLabel(Components[i]).Font.Name  := 'MS Sans Serif';
        TLabel(Components[i]).Font.Size  := 8;
        TLabel(Components[i]).Font.Style := [fsBold];
      end;
    end;
  end;
end;

但是这样做看起来很乱,对于一个简单的任务也会有相当多的代码。

想法 2

我知道我可以在设计时为每个控件一个一个地手动更改字体,但是要通过几种表单可能需要一些时间,即使那样我也可能会错过一个控件。

想法 3

与想法 2 类似,另一种方法是将表单视为文本 (DFM) 并以这种方式查找和替换字体。


基本上我会在我的应用程序中保持一致性,并且始终使用一种字体是我想要实现的目标。

我是否在这里遗漏了一些完全明显的东西,我试图为这样的任务做过度的事情吗?

4

3 回答 3

26

正如评论中所讨论的,关键是ParentFont属性。此属性在 VCL 层次结构中的各个点定义。如果您设置ParentFontTrue链中的所有组件,那么您只需修改即可更改整个应用程序的字体

Application.DefaultFont

默认情况下,大多数组件都设置ParentFontTrue,因此您无事可做。奇怪的是TForm。一个全新的默认表单已ParentFont设置为False. 这有点令人失望,但我怀疑这反映了一个事实,即 VCL 的原始设计者没有预料到这一点,并且ParentFont在 VCL 的开发中相对较晚才移植到这一点。

无论如何,在理想情况下,应用程序中的所有表单都应该派生自您控制的公共基类。如果是这样,那么您可以简单地在那里进行更改,设置ParentFont为 be True,确保没有明确的字体设置应用于表单上的任何组件,并且您是金色的。通过单个属性控制整个应用程序的字体。如果您的表单没有通用基类,那么现在是添加它的理想时机。如果您不想这样做,那么您需要ParentFont为每个表单进行设置。

其他相关属性是Screen.MessageFontScreen.MenuFont。这些提供了对消息框和菜单中使用的字体的全局控制。然而,最新版本的 Delphi 已将消息框和菜单的绘制控制权交还给 Windows,因此这些属性无效。

于 2012-05-14T19:48:04.157 回答
2

如前所述,真正的关键是确保您的所有表单都源自您自己的应用程序基础表单。

然后,您可以查看每个表单和按钮等,并查看属性,其中任何修改的字体属性都应以粗体显示,并且易于识别。大多数属性都有“恢复到继承”菜单选项。这应该基本上撤消任何先前的选择,而无需转到文本版本进行编辑。(尽管它可能正是这样做的,删除了以前字体设置产生的任何文本条目)。

我肯定想修复每个表单一次,而不是让它定义不正确并在运行时添加更多代码来修复它。如果您后来决定做一些不同的事情,那么这种变化会给您带来更严重的问题。

于 2012-05-17T15:46:01.307 回答
1

如果你想做这个运行时,就像你在想法 1 中描述的那样,你应该考虑把它变成一个递归函数,像这样:

procedure SetFontProperties(Control: TControl; Name: TFontName; Size: Integer; Styles: TFontStyles);
// Set font properties
var
  Index: Integer;
  Font: TFont;
  AnObject: TObject;
  ChildControl: TControl;
begin
  // Set font properties
  AnObject := GetObjectProp(Control, 'Font', nil);
  if AnObject is TFont then
  begin
    // Set properties
    Font := TFont(AnObject);
    Font.Name  := Name;
    Font.Size  := Size;
    Font.Style := Styles;
  end;

  // Set child font properties
  if Control is TWinControl then
  begin
    // Set
    for Index := 0 to TWinControl(Control).ControlCount - 1 do
    begin
      // Child control
      ChildControl := TWinControl(Control).Controls[Index];

      // Set font properties
      SetFontProperties(ChildControl, Name, Size, Styles);
    end;
  end;
end;

然后,您可以像这样使用它来为表单中的所有控件切换字体:

SetFontProperties(Self, 'Courier', 14, []);

然后该函数将设置窗体的字体属性,以及窗体上所有子控件的字体属性,包括嵌套在 TPanel 或其他容器控件中的控件。

但是,我确实同意您的看法,这是一种有点混乱的做法。

于 2012-05-14T20:02:33.517 回答