【问题标题】:Font smoothing in DelphiDelphi中的字体平滑
【发布时间】:2010-10-29 14:32:58
【问题描述】:

我有理由在 Delphi 表单上需要一个带有大字体的标签,并注意到 它的曲线仍然略微参差不齐。我将它与相同尺寸进行了比较 和 MSWord 中的字体更流畅。经过研究,我找到了代码 这让我可以平滑我的字体,但它很乱,我想知道是否 有更好的方法吗?查看 VCL 源代码,TFont 似乎与 NONANTIALIASED_QUALITY 相当令人沮丧...

谢谢布里

procedure TForm1.SetFontSmoothing(AFont: TFont);
var
  tagLOGFONT: TLogFont;
begin
  GetObject(
    AFont.Handle,
    SizeOf(TLogFont),
    @tagLOGFONT);
  tagLOGFONT.lfQuality  := ANTIALIASED_QUALITY;
  AFont.Handle := CreateFontIndirect(tagLOGFONT);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  I : integer;
begin
  For I :=0 to ComponentCount-1 do
    If Components[I] is TLabel then
      SetFontSmoothing( TLabel( Components[I] ).Font );
end;

【问题讨论】:

  • 那么这段代码是否有效(你只是想清理它并找到一些简单的方法)还是它仍然不够流畅或不起作用?
  • 您认为这段代码的哪一部分混乱?
  • 当 VCL 已经完成此操作时,我必须戳每个标签上的每个字体,这似乎很浪费。我寻找可以覆盖或子类但没有运气的东西。我想这是实现我想要的唯一方法。布里

标签: delphi fonts truetype smoothing


【解决方案1】:

发件人:http://objectmix.com/delphi/725245-tlabel-antialiasing-possibile-3.html

“只需​​使用支持字体平滑的字体即可解决此问题。Delphi 使用(或至少曾经使用)MS Sans Serif 作为默认值,而不是 支持平滑(ClearType 或其他)。如果您将字体设置为 Tahoma(最适合 XP)或 Segoe UI(最适合 Vista),您将 根据您的系统设置自动获得字体平滑 Delphi 应用程序。”

确认,它使用 Delphi XE 和 Win7 运行良好。现在正忙于更改我所有的字体;-)

【讨论】:

    【解决方案2】:

    恕我直言,VCL 应该检查系统默认字体平滑并将其应用为运行时的默认值。如果不是,至少它应该默认为更合理的平滑。在这种情况下,有人可能会争辩说,ClearType 会是一个更好的默认值,考虑到如今 > 50% 的显示器是 LCD(并且超过 50% 的机器运行 XP 或更高版本)。

    这是一个公认的 hack(正如 Ken White 所提到的,如果有替代方案,这不是最好的方法),但我需要一种方法来全局修复这个包含数百个第 3 方组件类型的表单(使组件继承不切实际)。

    我在Graphics.pas,TFont.GetHandle中更改了默认字体质量如下:

    // lfQuality := DEFAULT_QUALITY;

    lfQuality := 5; // (HACK) CLEARTYPE_QUALITY,强制清除类型

    【讨论】:

      【解决方案3】:

      您可以欺骗 VCL 创建您自己的继承自 TLabel 的类。 这是概念验证代码,使用 Delphi 4 进行了测试,应该可以帮助您入门。

      为你自己的TLabel类创建一个新单元:

      unit AntiAliasedLabel;
      
      interface
      
      uses
        Windows, Messages, SysUtils, Controls, StdCtrls, Graphics;
      
      type
        TLabel = class(StdCtrls.TLabel)
        private
          fFontChanged: boolean;
        public
          procedure Paint; override;
        end;
      
      implementation
      
      procedure TLabel.Paint;
      var
        LF: TLogFont;
      begin
        if not fFontChanged then begin
          Win32Check(GetObject(Font.Handle, SizeOf(TLogFont), @LF) <> 0);
          LF.lfQuality := ANTIALIASED_QUALITY;
          Font.Handle := CreateFontIndirect(LF);
          fFontChanged := TRUE;
        end;
        inherited;
      end;
      
      end.
      

      现在修改包含标签的表单单元,添加AntiAliasedLabel 单元之后 StdCtrls。这会导致在通常创建 StdCtrls.TLabel 的位置创建您自己的类 AntiAliasedLabel.TLabel

      【讨论】:

        【解决方案4】:

        最简单的方法是基于 TLabel 创建自己的组件,例如 TSmoothLabel 或 TAntiAliasedLabel,然后将平滑代码添加到其中。然后你使用你的组件而不是标准的 TLabel。

        【讨论】:

        • 是的,但我正在加载一个指定 TLabel 类的现有 DFM,因此如果有重新注册 TLAbel 的方法,您的建议可能会奏效。布里
        • 有一种方法,但它需要在运行时用自己的方法替换 TLabel.NewInstance VMT 条目。 JCL(JEDI 代码库)具有执行此操作的功能。
        • @Brian:你为什么不能只修复 DFM 和 PAS 文件(从 IDE 外部)以使用你的新类?替代方案:如果您使用的是支持它们的 Delphi 版本,则可以使用 TLabel 的类助手。 (指定将来使用哪个 Delphi。)不过,如果有任何其他方式,我不推荐使用 class helper 路由,因为它会影响其范围内的任何 TLabel。
        • @Andreas:这是错误的方法。这会影响任何地方的每一个 TLabel,并且依赖于在 VCL 的未来版本中处于相同位置的事物。当有其他方法不做时,切勿做黑客的事情。
        猜你喜欢
        • 2013-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-25
        • 1970-01-01
        相关资源
        最近更新 更多