Search code examples
delphifontstruetypesmoothing

Font smoothing in Delphi


I had cause to need a label with a large font on a Delphi form and noticed that its curves were still slightly jagged. I compared this with the same size and font in MSWord which was much smoother. After research I found code that allowed me to smooth my fonts but it's messy and I was wondering if there was a better way? Looking in the VCL source, TFont seems wedded to NONANTIALIASED_QUALITY which is rather frustrating...

Thanks 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;

Solution

  • You can trick the VCL into creating your own class that inherits from TLabel. This is proof-of-concept code, tested with Delphi 4, which should get you started.

    Create a new unit for your own TLabel class:

    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.
    

    Now modify your form unit that contains the label, adding the AntiAliasedLabel unit after StdCtrls. This results in your own class AntiAliasedLabel.TLabel being created where normally StdCtrls.TLabel would be created.