Table of Contents

Images and links

Inserting images

// Insert an image from a file at the cursor position
RichEditor1.InsertImage('photo.png');

// Insert from a bitmap
var bmp: TBitmap;
begin
  bmp := TBitmap.Create;
  try
    bmp.LoadFromFile('photo.png');
    RichEditor1.InsertImage(bmp);
  finally
    bmp.Free;
  end;
end;

Graphic selection handles

When a user clicks an embedded image, selection handles appear around it. The handle appearance is controlled by GraphicSelection:

Property Description
GraphicSelection.Color Background color of the selection grip squares
GraphicSelection.BorderColor Border color of the grip squares
GraphicSelection.Style gsRect for square handles, gsCircle for round handles
RichEditor1.GraphicSelection.Style := gsCircle;
RichEditor1.GraphicSelection.Color := gcDodgerBlue;
RichEditor1.GraphicSelection.BorderColor := gcWhite;
// Insert clickable link text at the cursor position. The display text is
// the first argument, the target URL the second.
RichEditor1.AddHyperlink('TMS Software', 'https://www.tmssoftware.com');

// Turn an existing selection into a hyperlink instead
RichEditor1.SetSelectionHyperlink('https://www.tmssoftware.com');

Auto-open URLs

URLOpen decides which gesture opens a link in the default browser: uoCtrl (the default) requires Ctrl+click, uoClick opens on a plain click, uoAlt on Alt+click, and uoNone never opens the link. URLAuto (uAuto by default) controls whether typed or pasted URLs are auto-detected and turned into links at all:

RichEditor1.URLOpen := uoClick;
RichEditor1.URLAuto := uAuto;

To handle link clicks yourself, assign OnClickHyperlink:

procedure TForm1.RichEditor1ClickHyperlink(Sender: TObject; URL: string);
begin
  // Custom handling instead of auto-open
  ShowMessage('Link clicked: ' + URL);
end;

Custom drawing the page background and graphic placeholders

Two hooks let you paint into the content area yourself. Use them when the document needs something the element model cannot express - a watermark, a printed-form background, or a placeholder whose visual is computed at runtime rather than stored in the document. For anything that is genuinely part of the content, insert a real element (InsertImage, AddHyperlink) instead, so it survives a save/load round trip.

Event Signature Fires
OnDrawBackground (Sender: TObject; ACanvas: TCanvas; ARect: TRect) Immediately after the page rectangle has been filled, before any element is painted.
OnDrawGraphic (Sender: TObject; ACanvas: TCanvas; ARect: TRect; AID: string) To paint a TGraphicElement placeholder, identified by the AID string it was inserted with.
procedure TForm1.RichEditorDrawBackground(Sender: TObject; ACanvas: TCanvas;
  ARect: TRect);
var
  r: TRectF;
begin
  // ARect is the page rectangle the editor has just filled: client
  // coordinates, already reduced by PageMargin and shifted by the scroll
  // offset. Derive everything from it rather than from the control bounds.
  r := RectF(ARect.Left, ARect.Top, ARect.Right, ARect.Bottom);

  ACanvas.Fill.Kind := TBrushKind.Solid;
  ACanvas.Fill.Color := $22C00000;
  ACanvas.Font.Size := 48;
  ACanvas.FillText(r, 'DRAFT', False, 1, [],
    TTextAlign.Center, TTextAlign.Center);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  TMSFNCRichEditor1.OnDrawBackground := RichEditorDrawBackground;

  TMSFNCRichEditor1.AddText('Quarterly report');
  TMSFNCRichEditor1.AddLineBreak;

  // A graphic element is a sized placeholder identified by a string ID; the
  // document stores the ID, not a bitmap.
  TMSFNCRichEditor1.InsertGraphic('signature', 120, 40);
end;

A graphic placeholder is created with InsertGraphic(AID, AWidth, AHeight). The document stores only the identifier and the reserved size, so the same document can render a different visual per application - a signature, a chart, a barcode - without embedding a bitmap.

Pitfalls

  • OnDrawBackground fires before the elements are drawn, so whatever you paint there sits behind the text. There is no matching after-content hook, so a foreground overlay is not available through this event.
  • Painting goes to the editor's offscreen buffer, not directly to the screen, and the buffer is not redrawn for a caret blink alone. Do not rely on the event as a timer.
  • ARect already accounts for PageMargin and the vertical scroll offset, and it changes as the user scrolls. Derive positions from ARect rather than from the control's own bounds.
  • The handler runs on every repaint. Keep it allocation-free; loading a bitmap from disk inside it will make scrolling stutter.
  • OnDrawGraphic is not raised on FMX targets. The FMX element painter currently renders every TGraphicElement as the red placeholder cross without consulting the event, so on FMX use an inserted image element for runtime visuals rather than a graphic placeholder.
RichEditor1.AddText('See the product page: ');
RichEditor1.AddHyperlink('TMS Software', 'https://www.tmssoftware.com');
RichEditor1.AddLineBreak;
RichEditor1.AddLineBreak;
RichEditor1.InsertImage('banner.png');
  • TTMSFNCRichEditorInsertImage, AddHyperlink, SetSelectionHyperlink, URLAuto, URLOpen, GraphicSelection, OnClickHyperlink, OnDrawBackground, OnDrawGraphic

See also