Table of Contents

Editing and formatting

Text selection

// Select all
RichEditor1.SelectAll;

// Select a range (character offset, length)
RichEditor1.Select(10, 5);

// Deselect
RichEditor1.ClearSelection;

Character formatting

Apply formatting to the current selection or the cursor position (affects new typing):

Property Type Description
Bold Boolean Bold text
Italic Boolean Italic text
Underline Boolean Underline
StrikeThrough Boolean Strikethrough
SuperScript Boolean Superscript
SubScript Boolean Subscript
FontName String Font family
FontSize Single Font size in points
FontColor TAlphaColor Text color
// Make selected text bold and red
RichEditor1.Bold := True;
RichEditor1.FontColor := gcRed;

Reading the same properties returns the formatting at the cursor or in the selection.

Paragraph formatting

Property Type Description
HorizontalTextAlign TTMSFNCGraphicsTextAlign gtaLeading, gtaCenter, gtaTrailing, gtaJustify
LineSpacing Single Line spacing multiplier
RichEditor1.HorizontalTextAlign := gtaCenter;

Lists

// Toggle ordered (numbered) list
RichEditor1.OrderedList := True;

// Toggle unordered (bulleted) list
RichEditor1.UnorderedList := True;

Indentation

RichEditor1.Indent;    // increase indent
RichEditor1.Outdent;   // decrease indent

Undo and redo

if RichEditor1.CanUndo then RichEditor1.Undo;
if RichEditor1.CanRedo then RichEditor1.Redo;

Inserting text

// Insert at cursor position
RichEditor1.InsertText('Hello, world!');

Reading content

// Plain text
var plain := RichEditor1.PlainText;

// HTML
var html := RichEditor1.HTML;

Clipboard: cut, copy, and paste

The editor exchanges more than plain text with the clipboard: a copy carries the selection as an internal rich-text stream, as RTF, and as plain text at the same time, so a paste back into the editor keeps its formatting while a paste into a plain-text field still works. Reach for the clipboard events when the document must not accept everything a user might paste - stripping tabs out of spreadsheet text, or refusing a multi-megabyte screenshot.

Member Purpose
CopyToClipboard Copies the selection in every format the editor produces.
CutToClipboard Copies the selection, then deletes it. A selected image is copied as a picture.
PasteFromClipboard Pastes the clipboard content over the selection. Returns the plain text that was inserted.
ClipboardHasContent True when the clipboard holds a format the editor can paste - use it to enable a Paste command.
ClipboardFormats The TClipboardFormat set (cfRTE, cfRTF, cfText, cfHTML, cfBMP, cfFile) the editor is willing to accept.
CopyRTFToClipboard, CopyHTMLToClipboard Place only the RTF or only the HTML representation on the clipboard.
Event Signature
OnPasteText (Sender: TObject; var AText: string; var Allow: boolean)
OnPasteBitmap (Sender: TObject; ABitmap: TTMSFNCBitmap; var Allow: boolean)
OnPasteFormattedText (Sender: TObject; AStream: TStream)
procedure TForm1.RichEditorPasteText(Sender: TObject; var AText: string;
  var Allow: boolean);
begin
  // AText is a var parameter, so rewriting it here changes what is inserted.
  AText := StringReplace(AText, #9, ' ', [rfReplaceAll]);
  Allow := Trim(AText) <> '';
end;

procedure TForm1.RichEditorPasteBitmap(Sender: TObject;
  ABitmap: TTMSFNCBitmap; var Allow: boolean);
begin
  // Keep an oversized screenshot out of the document rather than scaling it
  // after the fact.
  Allow := (ABitmap.Width <= 1600) and (ABitmap.Height <= 1600);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  TMSFNCRichEditor1.OnPasteText := RichEditorPasteText;
  TMSFNCRichEditor1.OnPasteBitmap := RichEditorPasteBitmap;

  // Accept rich text and plain text on paste, but never a bitmap.
  TMSFNCRichEditor1.ClipboardFormats := [cfRTF, cfText];
end;

procedure TForm1.PasteButtonClick(Sender: TObject);
var
  s: string;
begin
  // Use ClipboardHasContent to drive the enabled state of a Paste command;
  // it reports whether any pastable format is present at all.
  if not TMSFNCRichEditor1.ClipboardHasContent then
    Exit;

  // The result is the plain text that was inserted. It is empty when the
  // clipboard delivered rich text or a bitmap instead.
  s := TMSFNCRichEditor1.PasteFromClipboard;
  StatusLabel.Text := Format('Pasted %d characters of plain text', [Length(s)]);
end;

procedure TForm1.CopyButtonClick(Sender: TObject);
begin
  if TMSFNCRichEditor1.HasSelection then
    TMSFNCRichEditor1.CopyToClipboard
  else
    TMSFNCRichEditor1.SelectAll;
end;

procedure TForm1.CutButtonClick(Sender: TObject);
begin
  if TMSFNCRichEditor1.HasSelection then
    TMSFNCRichEditor1.CutToClipboard;
end;

Paste order and pitfalls

PasteFromClipboard walks the available formats in a fixed order - rich-text stream, then RTF, then bitmap, then plain text - and inserts the first match in each group it is allowed to use. Four consequences are worth knowing:

  • Rich text wins over plain text. The plain-text branch is skipped once a rich-text or RTF paste succeeded, so OnPasteText does not fire for a formatted paste. A sanitiser that only lives in OnPasteText is bypassed by any clipboard that also carries RTF; remove cfRTF from ClipboardFormats if plain text must always be the route in.
  • A bitmap is not mutually exclusive. The bitmap branch is not skipped by a preceding rich-text paste, so a clipboard holding both RTF and an image can insert both in one call.
  • The return value only reflects the plain-text branch. It is an empty string after a formatted or bitmap paste, which is not an error.
  • On FMX targets ClipboardFormats gates pasting only. A copy always publishes plain text, RTF, and (except on Android) the internal rich-text stream regardless of the set, so narrowing ClipboardFormats does not reduce what other applications see when they paste from your document.

Combining programmatic editing, formatting, and content retrieval

RichEditor1.SelectAll;
RichEditor1.Delete;

// Heading
RichEditor1.FontSize := 18;
RichEditor1.Bold := True;
RichEditor1.InsertText('Project Report');
RichEditor1.Bold := False;
RichEditor1.FontSize := 12;
RichEditor1.InsertLineBreak;
RichEditor1.InsertLineBreak;

// Paragraph
RichEditor1.HorizontalTextAlign := gtaLeading;
RichEditor1.InsertText(
  'This report summarizes the work completed in Q2.');
RichEditor1.InsertLineBreak;
RichEditor1.InsertLineBreak;

// Bulleted list
RichEditor1.UnorderedList := True;
RichEditor1.InsertText('Feature A completed');
RichEditor1.InsertLineBreak;
RichEditor1.InsertText('Feature B in progress');
RichEditor1.InsertLineBreak;
RichEditor1.UnorderedList := False;
  • TTMSFNCRichEditorBold, Italic, Underline, FontName, FontSize, FontColor, InsertText, SelectAll, Undo, Redo

See also

  • Images and links — embed images and insert hyperlinks
  • Toolbar — connect the toolbar for interactive formatting