Delphi中的字体平滑处理

20

我需要在Delphi表单上使用大号字体的标签,但发现其曲线仍然有些锯齿。我将其与MSWord中相同大小和字体的标签进行比较,后者要平滑得多。经过研究,我找到了一些代码可以使我的字体更平滑,但它很混乱,我想知道是否有更好的方法?查看VCL源代码,TFont似乎与NONANTIALIASED_QUALITY紧密耦合,这让人感到有些沮丧...

谢谢Bri

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;

3
这段代码是否有效(你只是想将其整理并找到一些简便的方法),还是仍然不够流畅或无法正常工作? - schnaader
你认为这段代码的哪一部分比较混乱? - Rob Kennedy
当VCL已经完成这项任务时,我必须在每个标签上检查每种字体,这似乎是浪费的。我尝试寻找一些可以重写或子类化的东西,但没有找到。我想这是实现我想要的唯一方法。 - Brian Frost
4个回答

29

你可以欺骗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.

现在修改包含标签的表单单元,在StdCtrls后面添加AntiAliasedLabel单元。这将导致您自己的类AntiAliasedLabel.TLabel被创建,而不是通常创建StdCtrls.TLabel


7
在我看来,VCL应该检查系统的默认字体平滑设置,并将其作为运行时的默认设置。如果不这样做,至少它应该采用更合理的平滑设置。可以说,在这种情况下,考虑到50%以上的显示器是LCD(大于50%的计算机正在运行XP或更高版本),ClearType会成为更好的默认设置。
这是一种公认的hack(正如Ken White所提到的,如果有其他替代方法,则不是最佳方法),但我需要一种方法来全局修复包含数百个第三方组件类型的窗体(使组件继承不现实)。
我在Graphics.pas中更改了默认的字体质量,TFont.GetHandle如下: lfQuality:= 5; //(HACK) CLEARTYPE_QUALITY,强制使用ClearType

5

来源:http://objectmix.com/delphi/725245-tlabel-antialiasing-possibile-3.html

"只需使用支持字体平滑处理的字体即可解决此问题。Delphi默认使用(或至少曾经使用)MS Sans Serif,该字体不支持平滑处理(ClearType或其他方式)。如果您将字体设置为Tahoma(最适用于XP)或Segoe UI(最适用于Vista),则会根据系统设置自动获得字体平滑处理效果在您的Delphi应用程序中。"

已确认,在Delphi XE和Win7上使用时可以完美解决。我现在正忙着更改所有字体;-)


3

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


是的,但我正在加载一个指定TLabel类的现有DFM,所以如果有一种重新注册TLabel的方法,你的建议可能有效。 - Brian Frost
1
有一种方法,但需要在运行时通过替换TLabel.NewInstance VMT条目为自己的方法来实现。JCL(JEDI代码库)有相应的函数可以完成此操作。 - Andreas Hausladen
3
@Brian: 为什么你不能在IDE之外修复DFM和PAS文件,以使用你的新类?如果你使用支持它们的Delphi版本,你可以为TLabel使用一个类助手。(请在未来指定哪个Delphi版本。)但是如果有其他方法,我不推荐使用类助手路线,因为它会影响到其作用域内的所有TLabel。 - Ken White
1
@Andreas:这是错误的方法。它会影响到每一个 TLabel,而且依赖于未来版本的 VCL 中的事物在相同的位置上。当有其他不是 hack 的方法时,永远不要使用 hack 方法。 - Ken White

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接