Printing
Printing from code means printing without asking the user each time: a delivery note after an order is saved, a stack of merged letters, all documents of a folder. TX Text Control prints through the PrintDocument class of .NET, both from the TextControl on your form and from a ServerTextControl that never shows the document. You choose the printer, the pages and the copies, combine several documents into one print job, print mail merge results and pick the printer whose measurements format the document.
The print dialog, the print preview and printing a single page from the editor are covered in Print a Document and Printing and Print Preview. The examples here are handlers in Form1.cs with the TextControl named textControl1; Form1.cs needs these using directives:
using System;
using System.Drawing.Printing;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using TXTextControl;
How Printing Works
Three classes print, all with a System.Drawing.Printing.PrintDocument:
| Member | Prints |
|---|---|
| TextControl.Print | The document in the editor; with a document name, after the user confirmed the print dialog |
| ServerTextControl.Print | A document your code loaded or created, without showing it and without a dialog |
| MailMerge.Print | The document a mail merge created |
All three use these settings of the PrintDocument: DocumentName, PrintController, DefaultPageSettings.Color and, in PrinterSettings, PrinterName, FromPage, ToPage, Copies, Collate, PrintToFile and PrintRange. FromPage and ToPage take effect only when PrintRange is PrintRange.SomePages, and without a PrinterName, the default printer prints. The overloads of TextControl.Print are listed in The Print Methods.
Before printing the editor's document, check CanPrint: a protected document can forbid printing.
Print Pages, Copies and Collated Sets
The following handler prints two collated copies of the pages the user enters in two NumericUpDown controls, on the printer the user selected in a ComboBox:
private void printPagesButton_Click(object sender, EventArgs e)
{
if (!textControl1.CanPrint)
{
return;
}
PrintDocument printDocument = new PrintDocument();
printDocument.DocumentName = "Quarterly Report";
printDocument.PrinterSettings.PrinterName = printerComboBox.Text;
// FromPage and ToPage are only used with PrintRange.SomePages
printDocument.PrinterSettings.PrintRange = PrintRange.SomePages;
printDocument.PrinterSettings.FromPage = (int)fromPageBox.Value;
printDocument.PrinterSettings.ToPage = Math.Min((int)toPageBox.Value, textControl1.Pages);
printDocument.PrinterSettings.Copies = 2;
printDocument.PrinterSettings.Collate = true;
// No "Printing page n" status dialog
printDocument.PrintController = new StandardPrintController();
textControl1.Print(printDocument);
}
private void Form1_Load(object sender, EventArgs e)
{
// The names of the installed printers
foreach (string printer in PrinterSettings.InstalledPrinters)
{
printerComboBox.Items.Add(printer);
}
printerComboBox.Text = new PrinterSettings().PrinterName;
}
The code works as follows:
PrinterSettings.InstalledPrinterslists the printers of the machine, and a newPrinterSettingsobject names the default printer.- Pages is the number of pages, which limits the range.
- A
StandardPrintControllerprints without the status dialog that .NET shows by default.
PrintToFile together with PrintFileName sends the output to a file, for example with the printer Microsoft Print to PDF. To create a PDF file, saving the document as PDF is the direct way, as Saving and Converting Documents describes.
Print Several Documents in One Print Job
The second overload of ServerTextControl.Print, Print(int page, PrintPageEventArgs e), prints one page into the page that .NET is printing. Called from the PrintPage event of a PrintDocument, it combines several documents into one print job, so that they come out of the printer together. The following handler prints a letter and an invoice with a ServerTextControl, page by page:
private void printBatchButton_Click(object sender, EventArgs e)
{
string[] files = { "letter.docx", "invoice.docx" };
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
int fileIndex = 0;
int pageNumber = 1;
tx.Load(files[fileIndex], StreamType.WordprocessingML);
PrintDocument printDocument = new PrintDocument();
printDocument.DocumentName = "Letter and invoice";
printDocument.PrintController = new StandardPrintController();
printDocument.PrintPage += (s, args) =>
{
tx.Print(pageNumber, args);
pageNumber++;
// All pages of this document are printed: load the next one
if (pageNumber > tx.Pages)
{
fileIndex++;
if (fileIndex < files.Length)
{
tx.Load(files[fileIndex], StreamType.WordprocessingML);
pageNumber = 1;
}
}
args.HasMorePages = fileIndex < files.Length;
};
printDocument.Print();
}
}
The code works as follows:
- The ServerTextControl is created with Create before any other member is used, and the
usingblock disposes it after printing. The editor on the form keeps its document. printDocument.Print()starts the job, and .NET raisesPrintPagefor each page. ServerTextControl.Pages tells when the last page of a document is reached.HasMorePagestells .NET whether another page follows.
A PrintPage handler can also draw its own content with args.Graphics before it calls Print, which prints the page on top of it, for example over a form background. Print Pages From Your Own PrintDocument explains the overload with the page of the editor.
Print Without Blocking the Form
Printing a long document takes time, and while Print runs, the form doesn't respond. A ServerTextControl can print on another thread, because it doesn't belong to the form:
private async void printInBackgroundButton_Click(object sender, EventArgs e)
{
printInBackgroundButton.Enabled = false;
await Task.Run(() =>
{
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
tx.Load("report.docx", StreamType.WordprocessingML);
PrintDocument printDocument = new PrintDocument();
printDocument.DocumentName = "report.docx";
printDocument.PrintController = new StandardPrintController();
tx.Print(printDocument);
}
});
// Back on the UI thread
printInBackgroundButton.Enabled = true;
}
The TextControl itself belongs to the UI thread and must not be used inside Task.Run. To print the document of the editor in the background, save it to a byte array first and load the array into the ServerTextControl, as Using ServerTextControl in Desktop Applications shows.
Print a Merged Document
MailMerge merges a template with data into the document of the text component it is connected to. Its Print method prints the result, with a PrintDocument or with a document name, a printer name, a number of copies and a collate flag:
private void printLettersButton_Click(object sender, EventArgs e)
{
string jsonData = File.ReadAllText("customers.json");
using (ServerTextControl tx = new ServerTextControl())
{
tx.Create();
TXTextControl.DocumentServer.MailMerge mailMerge = new TXTextControl.DocumentServer.MailMerge();
mailMerge.TextComponent = tx;
mailMerge.LoadTemplate("letter-template.docx", TXTextControl.DocumentServer.FileFormat.WordprocessingML);
mailMerge.MergeJsonData(jsonData);
// Document name, printer name, copies, collate
mailMerge.Print("Customer letters", "Microsoft Print to PDF", 1, false);
}
}
TextComponent connects the MailMerge with the ServerTextControl, LoadTemplate loads the template and MergeJsonData merges it with the JSON data. Mail Merge and Reporting describes templates and data.
Choose the Formatting Printer
TX Text Control formats text with the measurements of a device, so that line and page breaks on the screen match those on paper. FormattingPrinter names the printer whose measurements are used:
| Value | Formats with |
|---|---|
| The name of a printer | The measurements of that printer; if it isn't installed, the standard printer |
"Standard" | The standard printer of the system |
"Display" | The font measurements of the display device |
A document printed on its formatting printer has the same breaks as on the screen, and the paper sizes the editor offers depend on it, as Print Exactly What the Screen Shows shows. ServerTextControl.FormattingPrinter does the same for a ServerTextControl; give both the same value when a document goes from one to the other. A printer that responds late, such as a network printer in energy-saving mode, can delay the initialization of TX Text Control, as the blog article Initialize Text Control Without a Printer (Completely) explains.
Next Steps
- Printing and Print Preview: the print dialog and preview of the editor.
- Printing in Troubleshooting: when the printout differs from the screen.
- Using ServerTextControl in Desktop Applications: work in the background.
- Sections, Pages, Headers, and Footers: pages and page numbers.