Printing
TMS FNC Core provides a layered print library. Use the level that matches your needs:
| Class | Level | Use when |
|---|---|---|
TTMSFNCPrinter (via TMSFNCPrinter) |
Low-level | Full control over drawing; draw directly on printer canvas. |
TTMSFNCGraphicsPrintIO |
Mid-level | Print FNC components or graphics with header, footer, and page number. |
TTMSFNCGridPrintIO |
Component-specific | Multi-page grid export with repeat-fixed-cells and other grid options. |
TTMSFNCRichEditorPrintIO |
Component-specific | RichEditor export with automatic line breaks and new pages. |
Add the appropriate unit to your uses clause based on the chosen framework (FMX., VCL., or WEBLib.).
TTMSFNCPrinter
The low-level printer. Use the global TMSFNCPrinter instance. Place all drawing inside the OnDrawContent callback and call EndDoc at the end of the callback.
Warning
On Android, BeginDoc is asynchronous — drawing code after BeginDoc does not execute sequentially. Place all drawing inside OnDrawContent. Also add FNCPrintDocumentAdapter.jar (or the combined FNC JAR) to your project libraries.
uses
FMX.TMSFNCPrinters, FMX.TMSFNCGraphicsTypes;
procedure TForm1.PrintClick(Sender: TObject);
begin
TMSFNCPrinter.OnDrawContent :=
procedure
begin
TMSFNCPrinter.Graphics.Font.Color := gcBlue;
TMSFNCPrinter.Graphics.Font.Size := 40;
TMSFNCPrinter.Graphics.DrawText(0, 20,
TMSFNCPrinter.PageWidth, 100, 'Hello', False, gtaCenter, gtaCenter);
TMSFNCPrinter.Graphics.Fill.Color := gcRed;
TMSFNCPrinter.Graphics.DrawEllipse(100, 200, TMSFNCPrinter.PageWidth - 100, 300);
TMSFNCPrinter.EndDoc;
end;
TMSFNCPrinter.BeginDoc;
end;
TMSFNCPrinter Methods
| Method | Description |
|---|---|
BeginDoc |
Start a new print document. On Android this triggers the asynchronous print flow; place all drawing in OnDrawContent. |
EndDoc |
Close the document and send it to the printer. Call this at the end of OnDrawContent. |
NewPage |
Add a new page to the document. |
TMSFNCPrinter callbacks
| Event | Description |
|---|---|
OnDrawContent |
Fired when the printer is ready to receive drawing commands. Place all TTMSFNCGraphics calls here and call EndDoc at the end. On Android this is the only supported location for drawing code. |
TMSFNCPrinter Properties
| Property | Description |
|---|---|
Device |
Active printer name (not used on WEB, Android, iOS) |
DPI |
Printer DPI (settable on WEB and Android) |
Graphics |
TTMSFNCGraphics for drawing on the printer canvas |
Orientation |
poPortrait or poLandscape |
PageWidth / PageHeight |
Page dimensions in pixels (PageWidth/PageHeight settable on WEB) |
PageNumber |
Zero-based index of the current page |
PrintJobName |
Android: print job name |
PrintSize |
Android: paper size |
PrintCompleted |
iOS: True when print is complete |
TTMSFNCGraphicsPrintIO
A mid-level wrapper that adds header, footer, page number, and layout margins on top of TTMSFNCPrinter. It can also export FNC components directly.
uses
FMX.TMSFNCPrintIO;
procedure TForm1.PrintClick(Sender: TObject);
var
r: TRectF;
begin
TMSFNCGraphicsPrintIO1.Options.Header := 'My Report';
TMSFNCGraphicsPrintIO1.Options.Footer := 'My Footer Text';
TMSFNCGraphicsPrintIO1.Options.PageNumber := pnHeader;
TMSFNCGraphicsPrintIO1.Options.PageNumberFormat := 'Page %d';
r := RectF(
TMSFNCGraphicsPrintIO1.Options.Margins.Left,
TMSFNCGraphicsPrintIO1.Options.Margins.Top,
TMSFNCGraphicsPrintIO1.Options.Margins.Left + TMSFNCGrid1.Width,
TMSFNCGraphicsPrintIO1.Options.Margins.Top + TMSFNCGrid1.Height);
TMSFNCGraphicsPrintIO1.Print(TMSFNCGrid1, r);
end;
Print Methods
| Method | Description |
|---|---|
Print |
Print without an export object (use OnDrawContent) |
Print(AExportObject, AExportRect) |
Print a single FNC component into a rectangle |
Print(AExportObjects) |
Print an array of FNC components |
Print(AExportObjects, AExportRects) |
Print multiple components into respective rectangles |
TTMSFNCPrintIOOptions
| Property | Description |
|---|---|
DefaultFont |
TTMSFNCGraphicsFont applied to all text unless overridden by HeaderFont, FooterFont, or PageNumberFont |
Header / Footer |
Header/footer text |
HeaderSize / FooterSize |
Height of header/footer area |
HeaderFont / FooterFont |
Font for header/footer text |
HeaderMargins / FooterMargins |
Margins around header/footer |
HeaderHorizontalAlignment / FooterHorizontalAlignment |
Text alignment |
PageNumber |
pnNone, pnHeader, or pnFooter |
PageNumberFormat |
Format string |
PageNumberFont / PageNumberSize / PageNumberMargins |
Page number appearance |
Margins |
Page margins |
Device |
Printer device name |
PageOrientation |
Portrait or landscape |
Header, footer, and page-number placement
Each of the three bands is a rectangle, and the text inside it is positioned by an alignment pair rather than by coordinates. Reach for these when a band is taller than its text — a 40pt header with a one-line caption, a footer that must hug the content, or a page number that has to share the header strip with the header caption.
Every band's rectangle is derived from the page edges plus its own size and margins:
| Band | Rectangle |
|---|---|
| Header | Full page width inset by HeaderMargins, HeaderSize tall, measured down from the top. |
| Footer | Full page width inset by FooterMargins, FooterSize tall, measured up from the bottom. |
| Page number | Full page width inset by PageNumberMargins, PageNumberSize tall, at the top for pnHeader and at the bottom for pnFooter. |
Text is then placed inside that rectangle by the matching alignment pair, using TTMSFNCGraphicsTextAlign values (gtaLeading, gtaCenter, gtaTrailing):
| Property | Default | Controls |
|---|---|---|
HeaderHorizontalAlignment / HeaderVerticalAlignment |
gtaCenter / gtaCenter |
Header text inside the header band. |
FooterHorizontalAlignment / FooterVerticalAlignment |
gtaCenter / gtaCenter |
Footer text inside the footer band. |
PageNumberHorizontalAlignment / PageNumberVerticalAlignment |
gtaTrailing / gtaCenter |
Page-number text inside the page-number band. |
uses
FMX.TMSFNCPrintIO, FMX.TMSFNCGraphicsTypes;
procedure TForm1.ConfigurePrintLayout;
var
Options: TTMSFNCPrintIOOptions;
begin
Options := TMSFNCGraphicsPrintIO1.Options;
{ Header band: 40pt tall, text pinned to the bottom-left of the band so it
sits just above the content area. }
Options.Header := 'Quarterly sales report';
Options.HeaderSize := 40;
Options.HeaderMargins.Left := 24;
Options.HeaderMargins.Top := 12;
Options.HeaderHorizontalAlignment := gtaLeading;
Options.HeaderVerticalAlignment := gtaTrailing;
{ Footer band: text centered horizontally, pinned to the top of the band. }
Options.Footer := 'Confidential - internal use only';
Options.FooterSize := 30;
Options.FooterHorizontalAlignment := gtaCenter;
Options.FooterVerticalAlignment := gtaLeading;
{ The page-number band is computed from the page edges independently of the
header band, so with pnHeader the two share the same strip. Keep the page
number on the right (the default) so it does not overlap the header text. }
Options.PageNumber := pnHeader;
Options.PageNumberFormat := 'Page %d';
Options.PageNumberSize := 40;
Options.PageNumberMargins.Right := 24;
Options.PageNumberHorizontalAlignment := gtaTrailing;
Options.PageNumberVerticalAlignment := gtaTrailing;
TMSFNCGraphicsPrintIO1.Print;
end;
Three things the source makes explicit:
- The page-number band is independent of the header/footer band, not nested in it. Both are computed from the page edges, so with
PageNumber := pnHeaderthe page number is drawn over the same strip as the header. They do not collide by default only because the page number defaults togtaTrailingwhile the header defaults togtaCenter. If you centre the page number, give the two bands different sizes or margins. PageNumberFormatis aFormatstring with exactly one%d. It is pre-filled with'%d'only at design time — a print IO created in code starts with an empty format string, so the page number renders as nothing until you assign one. Extra placeholders raise a formatting error.PageNumber := pnNone(the default) skips the page-number band entirely, alignment and margins included.
TTMSFNCGraphicsPrintIO Properties
| Property | Description |
|---|---|
Options |
TTMSFNCPrintIOOptions for header, footer, page number, margins, and device settings |
ExportObject |
Sets the FNC component to export (alternative to passing via Print()) |
BitmapContainer |
TTMSFNCBitmapContainer attached to the graphics context during export, so named bitmaps resolve correctly when the exported component draws them |
Draw callbacks
| Event | Description |
|---|---|
OnBeforeDrawHeader / OnAfterDrawHeader |
Before/after header drawing; set ADefaultDraw := False for custom drawing |
OnBeforeDrawFooter / OnAfterDrawFooter |
Before/after footer drawing |
OnBeforeDrawPageNumber / OnAfterDrawPageNumber |
Before/after page number drawing |
OnBeforeDrawContent / OnAfterDrawContent |
Before/after each export object drawing |
OnAfterDraw |
Fired once when all drawing (including headers, footers, and all export objects) is complete |
OnCanCreateNewPage |
Control whether a new page is created before the next component |
OnGetExportRect |
Modify the export rectangle before rendering |
Putting it together: custom header with multi-component export
The example below exports a chart and a grid on the same page, attaches a bitmap container for image resolution, and draws a logo in the header alongside the default header text.
uses
FMX.TMSFNCPrintIO, FMX.TMSFNCBitmapContainer, FMX.TMSFNCGraphicsTypes;
procedure TForm1.PrintReportClick(Sender: TObject);
var
objs: TTMSFNCPrintIOExportObjectArray;
rects: TTMSFNCPrintIOExportRectArray;
topMargin, leftMargin: Single;
begin
// Attach a bitmap container so embedded images render during export
TMSFNCGraphicsPrintIO1.BitmapContainer := TMSFNCBitmapContainer1;
TMSFNCGraphicsPrintIO1.Options.Header := 'Quarterly Report';
TMSFNCGraphicsPrintIO1.Options.HeaderSize := 40;
TMSFNCGraphicsPrintIO1.Options.PageNumber := pnFooter;
TMSFNCGraphicsPrintIO1.Options.PageNumberFormat := 'Page %d';
// Draw a logo in the right half of the header area instead of default text
TMSFNCGraphicsPrintIO1.OnBeforeDrawHeader :=
procedure(AExportObject: TTMSFNCPrintIOExportObject; APageIndex: Integer;
ARect: TRectF; AGraphics: TTMSFNCGraphics; AHeader: string;
var ADefaultDraw: Boolean)
var
logoRect: TRectF;
begin
logoRect := RectF(ARect.Right - 80, ARect.Top + 4, ARect.Right - 4, ARect.Bottom - 4);
AGraphics.DrawBitmapName('logo', logoRect);
ADefaultDraw := True; // still draw the text on the left side
end;
// Place chart above the grid, each object on its own portion of the page
leftMargin := TMSFNCGraphicsPrintIO1.Options.Margins.Left;
topMargin := TMSFNCGraphicsPrintIO1.Options.Margins.Top;
SetLength(objs, 2);
objs[0] := TMSFNCChart1;
objs[1] := TMSFNCGrid1;
SetLength(rects, 2);
rects[0] := RectF(leftMargin, topMargin,
leftMargin + TMSFNCChart1.Width,
topMargin + TMSFNCChart1.Height);
rects[1] := RectF(leftMargin, rects[0].Bottom + 8,
leftMargin + TMSFNCGrid1.Width,
rects[0].Bottom + 8 + TMSFNCGrid1.Height);
TMSFNCGraphicsPrintIO1.Print(objs, rects);
end;
TTMSFNCGridPrintIO
Extends TTMSFNCGraphicsPrintIO for multi-page grid export. Assign the grid to the Grid property and call Print. The component handles page breaks automatically.
uses
FMX.TMSFNCGridPrintIO;
procedure TForm1.PrintClick(Sender: TObject);
begin
TMSFNCGridPrintIO1.Grid := TMSFNCGrid1;
TMSFNCGridPrintIO1.Options.Footer := 'My Footer Text';
TMSFNCGridPrintIO1.Options.PageNumber := pnHeader;
TMSFNCGridPrintIO1.Options.PageNumberFormat := 'Page %d';
TMSFNCGridPrintIO1.Print;
end;
TTMSFNCGridPrintIOOptions
Extends TTMSFNCPrintIOOptions with grid-specific output control:
| Property | Default | Description |
|---|---|---|
CellLayout |
gclFull |
How cells are rendered: gclFull (full cell with borders and background), gclColor (color only, no borders), gclNone (plain text) |
RepeatFixedRows |
False |
Repeat fixed rows at the top of each new page |
RepeatFixedColumns |
False |
Repeat fixed columns at the left of each new page |
FitToPage |
True |
Scale the grid width to fit the printable page width |
TTMSFNCGridPrintIO callbacks
| Event | Description |
|---|---|
OnRowIsPageBreak |
Fired before each row is printed. Set IsPageBreak := True to force a page break before the row. Use this to keep logical groups of rows together. |
OnBeforeDrawContent / OnAfterDrawContent |
Inherited from TTMSFNCGraphicsPrintIO |
TTMSFNCRichEditorPrintIO
Prints TTMSFNCRichEditor content with automatic line break detection and multi-page flow. Assign the editor to the RichEditor property and call Print. The component calculates where lines wrap at the page width and inserts page breaks automatically — no manual pagination is needed.
uses
FMX.TMSFNCRichEditorPrintIO;
procedure TForm1.PrintClick(Sender: TObject);
begin
TMSFNCRichEditorPrintIO1.RichEditor := TMSFNCRichEditor1;
TMSFNCRichEditorPrintIO1.Options.PageNumber := pnHeader;
TMSFNCRichEditorPrintIO1.Print;
end;
TTMSFNCRichEditorPrintIOOptions
Extends TTMSFNCPrintIOOptions with one additional property:
| Property | Default | Description |
|---|---|---|
ExportImages |
True |
Include images from the rich editor in the printed output. Set to False for text-only output. |
Related API
| API | Purpose |
|---|---|
TTMSFNCPrinter |
Low-level printer singleton |
TTMSFNCGraphicsPrintIO |
Mid-level component export with header/footer |
TTMSFNCPrintIOOptions |
Header, footer, page number, and margin options |