Search code examples
delphigdi+

Creating a floating anti-aliased text window in Delphi


I want to create a floating (top level) window that shows only Anti-Aliased text (no other window elements). I am trying to draw the text using GDI+ to maintain the alpha channel on the text rendering bitmap, but I'm having limited success.

I am able to create a transparent bitmap, but it looks as if the text drawing function thinks the background is black and not transparent, causing bad aliasing artifacts.

I've attached the full code, what am I missing? :

uses GDIPAPI ,GDIPOBJ;

var
  GDIPToken: ULONG;
  GDIStartupInput: TGDIPlusStartupInput;

procedure TOSDInfoForm.FormCreate(Sender: TObject);
var
  bmp: TBitmap;
  blend: TBLENDFUNCTION;
  pointSrc, pointForm: TPoint;
  bmpsize: TSize;
  g: TGPGraphics;
  fontFamily: TGPFontFamily;
  font: TGPFont;
  brush: TGPSolidBrush;
  status: TStatus;
begin
  BorderStyle := bsNone;
  FormStyle := fsStayOnTop;

  SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or WS_EX_LAYERED);

  GDIStartupInput.SuppressBackgroundThread := False;
  GDIStartupInput.SuppressExternalCodecs := False;
  GDIStartupInput.GdiplusVersion := 1;
  GdiplusStartup(GDIPToken, @GDIStartupInput, nil);

  bmp := TBitmap.Create;
  try
    bmp.PixelFormat := pf32bit;
    bmp.Width  := Width;
    bmp.Height := Height;

    g := TGPGraphics.Create(bmp.Canvas.Handle);
    try
      //g.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);
      g.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
      g.Clear(MakeColor(0, 0, 0, 0));  // Clear with full transparent

      fontFamily := TGPFontFamily.Create('Arial');
      font := TGPFont.Create(fontFamily, 32, FontStyleRegular, UnitPixel);
      brush := TGPSolidBrush.Create(MakeColor(255, 255, 0, 0)); // Red text

      g.DrawString('Hello, World!', -1, font, MakePoint(10.0, 10.0), brush);

      brush.Free;
      font.Free;
      fontFamily.Free;
    finally
      g.Free;
    end;

    pointSrc := Point(0, 0);
    pointForm := Point(Left, Top);

    bmpsize.cx := bmp.Width;
    bmpsize.cy := bmp.Height;

    blend.BlendOp := AC_SRC_OVER;
    blend.BlendFlags := 0;
    blend.SourceConstantAlpha := 255; // Opaque
    blend.AlphaFormat := AC_SRC_ALPHA;

    UpdateLayeredWindow(Handle, 0, @pointForm, @bmpsize, bmp.Canvas.Handle, @pointSrc, 0, @blend, ULW_ALPHA);
  finally
    bmp.Free;
  end;
end;

procedure TOSDInfoForm.FormDestroy(Sender: TObject);
begin
  GdiplusShutdown(GDIPToken);
end;

EDIT: The code above is functional thanks to Tom's tip, feel free to use it in your own code, take into account it uses GDI+ which requires at least Windows 7 to work without having to manually install GDI+.


Solution

  • You want to use anti-aliased rendering, ergo, change the current

    g.SetTextRenderingHint(TextRenderingHintClearTypeGridFit);

    to

    g.SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);