Search code examples
windowsdelphiwinapidelphi-2006

How can I override ClearType setting when drawing text using the Win32 API?


I have written a little application that draws text on in-memory images and writes them to files. The basic Delphi code looks similar to:

var
   Canvas : tCanvas;
   Text : WideString;
   TextRect : tRect;
begin
   Canvas := Bitmap.Canvas;
   Canvas.Brush.Color := clBlack;
   Canvas.Pen.Color := clBlack;
   Canvas.Font.Name := 'Courier New';
   Canvas.Font.Size := 11;
   Canvas.Font.Color := clWhite;

   TextRect := ...;  // calculate text position
   DrawTextW(Canvas.Handle, PWideChar(Text), Length(Text), TextRect, DT_NOCLIP or DT_NOPREFIX or DT_SINGLELINE or DT_CENTER or DT_VCENTER);
end;

Unfortunately the drawn text is different depending on the ClearType setting of the computer running the application. I would like to have a consistent output in my application regardless of the local ClearType setting (output is not displayed to screen directly anyway). Is there some Win32 API option to override the local ClearType settings?


Solution

  • The font smoothing of text is determined by the font that you select into the device. To learn about the options offered by the raw Win32 interface, read the LOGFONT documentation.

    In Delphi the underlying Win32 API font API is wrapped up by the TFont class. The property that is pertinent to this question is Quality. The default value is fqDefault which uses the system-wide font smoothing setting. You want to set Quality to either fqAntialiased or fqNonAntialiased.

    Older versions of Delphi do not have this property. In which case you will need to call CreateFontIndirect to create an HFONT with the required quality settings. You can call this function immediately before you start drawing text:

    procedure SetFontQuality(Font: TFont; Quality: Byte);
    var
      LogFont: TLogFont;
    begin
      if GetObject(Font.Handle, SizeOf(TLogFont), @LogFont) = 0 then
        RaiseLastOSError;
      LogFont.lfQuality := Quality;
      Font.Handle := CreateFontIndirect(LogFont);
    end;
    

    Pass either NONANTIALIASED_QUALITY or ANTIALIASED_QUALITY depending on your needs.