整个项目的字体一致性?

Posted

技术标签:

【中文标题】整个项目的字体一致性?【英文标题】:Font consistency throughout Project? 【发布时间】:2012-05-22 06:02:54 【问题描述】:

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

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

通常为表单设置字体而不是特定控件会将该表单上的所有控件更改为指定的字体。

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

想法 1

我正在考虑使用 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) 并以这种方式查找和替换字体。


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

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

【问题讨论】:

如果您手动更改控件的字体,您还将其ParentFont 属性设置为False;将其设置为True 以返回默认(父)字体 偷偷摸摸,我没有意识到这个属性已经被改变了! 在创建任何表单之前,请设置 Application.DefaultFont.Name := 'MS Sans Serif';,正如 Serg 指出的那样,在表单中将 ParentFont 设置为 true。要在消息对话框中设置字体,请设置Screen.MessageFont.Nameproperty。 如果您需要在运行时执行此操作,您可以像上面那样迭代表单组件并检查哪些组件具有使用 IsPublishedProp(Components[i], 'Font' 发布的 Font 属性) 来自 TypInfo 单元的方法。然后,您可以破解 TControl 来设置组件的 Font 属性,即, 如果您从 .dfm 文件中去除所有 Font 和 ParentFont 属性,那么 ParentFont 默认为 True,这一切都很好。 【参考方案1】:

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

Application.DefaultFont

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

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

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

【讨论】:

您和其他人已经评论过的内容没有什么可补充的了。如果项目选项中有一个选项来设置字体样式并将其应用于项目,那不是很好吗,就像Application.DefaultFont 的工作方式一样——如果像我一样不知道这个内置功能,拥有全局更改字体的视觉设置会更容易。无论如何,我接受您的回答,因为信息写得很好,并且 +1 用于突出显示消息和菜单。 请记住,VCL 表单不像 Swing (java) 或 WPF (C#/.net) 那样“布局管理”,并且在运行时更改字体会导致完美的字体剪裁,并使您的UI 混乱不堪。祝你好运。如果不手动、逐个查看结果以提高可读性,就无法更改应用程序字体。 @Warren 这是一个很好的观点,我打算在我的回答中提到它,但忘记了。在我的应用程序中,我在 XP 的 Tahoma 8 或 Vista+ 的 Segoe UI 9 中显示字体。这需要调用 ChangeScale 来更改表单布局。但是是的,您必须检查两种变体中的表格。只要您不将标签彼此硬塞在一起,就不会出现问题。 ParentFont 在所有这些方面都创造了奇迹。 我将自己尝试一下,并且可能会在博客中介绍结果。 +1 表示“应用程序中的所有表单都应派生自您控制的公共基类”。【参考方案2】:

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

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

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

【讨论】:

【参考方案3】:

如果你想做这个运行时,就像你在想法 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 或其他容器控件中的控件。

但是我同意你的观点,这是一种有点混乱的做法。

【讨论】:

这样的编码并不理想,但你的回答还是很有用的:) @MarjanVenema 这只是一个插图。如果您有部署其他字体属性名称的非 VCL 组件,当然,您将不得不使用这些属性名称来扩展功能。然而,这个讨论的重点是 Warren P 在上面的评论中提到的一点:通常像这样改变字体属性运行时是不可行的,因为它会改变对齐方式,引入字体剪辑等。

以上是关于整个项目的字体一致性?的主要内容,如果未能解决你的问题,请参考以下文章

android-解决EditText的inputType为Password时, 字体不一致的问题

sealer 成为 CNCF Sandbox 项目,旨在构建分布式应用交付新标准

组合模式

修复 Mobile Safari (iPhone) 上文本呈现不一致且某些字体比其他字体大的字体大小问题?

有哪些小细节可以让你的Excel显得专业

修改myeclipse字体与操作系统的字体一致