Sending data to the printer
For desktop apps, printing is very similar to drawing to the screen. But instead of drawing into a Graphics object of a Canvas control, you draw to a Graphics object created specifically for printing. There are methods available to allow you to create new pages and get printer settings.
For web apps, printing is far more limited. Usually what works best is to create HTML, display it in an HTML Viewer control and then print that.
Before printing anything, you usually want to give the user the ability to select the printer they want to use. This is done using the PrinterSetup class, which displays the Page Setup dialog for the operating system. In addition, this class returns the settings so that you can use them again later without prompting the user.
// PrinterSettings is a String property on the Window Var ps As New PrinterSetup ps.Settings = mPrinterSettings If ps.PageSetupDialog Then PrinterSettings = ps.Settings End If
Since PrinterSettings is a String, you can save it outside of your app (such as in a database or a file) for use the next time the user prints.
The PrinterSetup class has properties for printer settings such as landscape, page size and resolution. The PrinterSetup page has more details on these properties.
PrinterSetup is not supported in Linux apps.
Printing text and graphics
To print text and graphics you draw to the Graphics object for the printer. To get this Graphics objects, you call either the ShowPrinterDialog or PrinterSetup.OpenPrinter global methods. The only difference between these two methods is that one displays the Print dialog and the other does not. Since the printing system on macOS has the automatic capability to print to PDF, you can use this method to easily generate PDF files. On Windows you can install a "Print to PDF" printer driver to enable sending printed output to PDF files. If you need to generate PDF files, you can also use the PDFDocument class.
Since you are drawing to a Graphics object, all the commands covered in the Getting Started with Graphics topic can be used.
In addition, you also use the printing-specific method, NextPage to create multiple pages. This code prints “Hello” on page 1 and “World” on page 2:
Var ps As New PrinterSetup If ps.ShowPageSetupDialog Then Var page As Graphics page = ps.ShowPrinterDialog If page <> Nil Then // Draw text on page 1 with 1 inch left/top margin page.DrawText("Hello", ps.HorizontalResolution, ps.VerticalResolution) page.NextPage // Draw text on page 2 with 1 inch left/top margin page.DrawText("World", ps.HorizontalResolution, ps.VerticalResolution) End If End If
You can also use any printer settings that were previously stored from using the PrinterSetup class.
Var ps As New PrinterSetup ps.Settings = PrinterSettings // Property containing previously saved settings If ps.PageSetupDialog Then PrinterSettings = ps.Settings // Get new settings Var page As Graphics // Use Printer Settings page = ps.ShowPrinterDialog If page <> Nil Then // Draw text on page 1 with 1 inch left/top margin page.DrawText("Hello", ps.HorizontalResolution, ps.VerticalResolution) page.NextPage // Draw text on page 2 with 1 inch left/top margin page.DrawText("World", ps.HorizontalResolution, ps.VerticalResolution) End If End If
Each time you call NextPage, the current page is sent to the printer and the graphics object (in this case page) is cleared so that you can immediately begin drawing the new content. The final page gets sent to the printer when the page goes out of scope.
To print without displaying the Printer dialog, you call the OpenPrinter method:
Var ps As New PrinterSetup Var page As Graphics page = PrinterSetup.OpenPrinter(ps) If page <> Nil Then // Draw text on page 1 with 1 inch left/top margin page.DrawText("Hello", ps.HorizontalResolution, ps.VerticalResolution) page.NextPage // Draw text on page 2 with 1 inch left/top margin page.DrawText("World", ps.HorizontalResolution, ps.VerticalResolution) page.NextPage End If
Printing multiple pages of text
To print multiple pages, you need to parse each line and print it if it will fit on the page. If it will not fit, then you call NextPage so that your text will start printing at the top of the next page.
A common thing to do is to split the text into paragraphs and then track the height of the page and the height of the next paragraph to print to make sure that it will fit onto the page. If it will not fit, then the current page is sent to the printer and a new page is created to start printing the next paragraph.
This code shows you how you can print text from a TextArea onto multiple pages:
Var ps As New PrinterSetup If ps.ShowPageSetupDialog Then Var page As Graphics page = ps.ShowPrinterDialog If page <> Nil Then // Draw text on page 1 with 1 inch left/top margin Var leftMargin As Double = ps.HorizontalResolution Var topMargin As Double = ps.VerticalResolution page.FontSize = FontPopup.Text.Val // To print multiple pages, you need to parse each line and print it // if it will fit on the page. If it will not fit, then // you call NextPage so that your text will start printing at the top // of the next page. // First, split the text into multiple paragraphs Var paragraphs() As String = TextArea1.Text.ReplaceLineEndings(EndOfLine).ToArray(EndOfLine) Var pageTextHeight As Double = topMargin Var newpageTextHeight As Double Var lineWidth As Double For i As Integer = 0 To paragraphs.LastIndex newpageTextHeight = pageTextHeight + page.TextHeight(paragraphs(i), ps.Width - leftMargin * 2) If newPageTextHeight > ps.Height - topMargin * 2 Then // String does not fit on page, so move to next page page.NextPage pageTextHeight = topMargin newpageTextHeight = pageTextHeight + page.TextHeight(paragraphs(i), ps.Width - leftMargin * 2) End If // If string fits on page, then draw it page.DrawText(paragraphs(i), leftMargin, pageTextHeight, ps.Width - leftMargin * 2) // Keep a cumulative count of the pageheight as strings are added to it pageTextHeight = newpageTextHeight // Adjust page text height pageTextHeight = pageTextHeight + topMargin / 8 // 1/8 inch between paragraphs Next End If End If
The above code gives you a lot of control, but it is more work to track everything yourself. In the next section you'll see how you can take advantage of StyledTextPrinter to make this easier.
Printing styled text
Because TextAreas are capable of displaying styled text and multiple font sizes, you will usually want to retain the styled text when you print. The StyledTextPrinter class is used for this purpose, using the DrawBlock method.
The StyledTextPrinter class only works with MacOS apps.
To print styled text, you first create a StyledTextPrinter object and then call the StyledTextPrinter method of the TextArea (specifying the graphics to use and the width of the text) to get an instance of a StyledTextPrinter that can be used for printing.
With this instance, you can call the DrawBlock method to draw the styled text to the page (specifying the starting coordinates and the height).
This code prints styled text in a TextArea:
Var stp As StyledTextPrinter Var g As Graphics Var p As New PrinterSetup If p.ShowPageSetupDialog Then g = ps.ShowPrinterDialog If g <> Nil Then // Set width as 7.5 inches stp = PrintTextArea.StyledTextPrinter(g, 7.5 * p.HorizontalResolution) Do Until stp.EndOfText // Fill the page with text // at 10 inches height stp.DrawBlock(0, 0, 10 * p.VerticalResolution) If Not stp.EndOfText Then // There is more text, so add a page g.NextPage End If Loop End If End If
In order to support styled printing, the Text Area must have both its Multiline and Styled properties ON (True).
If the text to print is larger than what will fit in the specified block, then you can iterate through the text until it is all printed. You do this by checking the EOF property of the StyledTextPrinter class after each call to DrawBlock.
This code prints the contents of a Text Area into two columns with a quarter inch spacing between the columns:
Var g As Graphics Var p As New PrinterSetup If p.ShowPageSetupDialog Then g = ps.ShowPrinterDialog // 1 inch margin Var leftRightMargin As Double = 1 * p.HorizontalResolution Var topBottomMargin As Double = 1 * p.VerticalResolution // Page width after accounting for margins Var pageWidth As Double = p.Width - (leftRightMargin * 2) // Column gap is 1/4 of the margin (so, 1/4 inch) Var columnGap As Double = leftRightMargin / 4 // Calculate the column width // Subtract column gap from page with and // split result 2 Var columnWidth As Double = (pageWidth - columnGap) / 2 // Page size after accounting for margins Var pageHeight As Double = p.Height - (topBottomMargin * 2) Var stp As StyledTextPrinter stp = PrintTextArea.StyledTextPrinter(g, pageWidth) stp.Width = columnWidth Var columnToPrint As Integer = 1 Do Until stp.EndOfText stp.DrawBlock(leftRightMargin + (columnWidth + columnGap) * (columnToPrint - 1), _ topBottomMargin, pageHeight) If columnToPrint = 2 Then // printing last column If Not stp.EndOfText Then // more text to print g.NextPage columnToPrint = 1 End If Else // more columns to print on this page columnToPrint = columnToPrint + 1 End If Loop End If
Another technique you can use is to create what you want to print using HTML, display it in an HTMLViewer and then call its print method. This can sometimes be useful for simple reports. As a simple example, this code loads an HTMLViewer with some HTML:
Var html As String = "<body><em>Hello</em>, World!</body>" HTMLViewer1.LoadPage(html, FolderItem.TemporaryFile)
This code then displays the print dialog for the user to print the HTML:
Web printing is considerably simpler than desktop printing because it is much more restricted. Your web application runs in a web browser, so you are limited by what a web browser can print.
Web browsers generally do a good job of printing HTML, so in order to generate something to print, you want to first render it as HTML (either to a string or a file) and use an HTML Viewer control to display the HTML. Once you have what you want displayed in an HTML Viewer, you can have a button that calls the Print method of the HTML Viewer to ask the browser to print its contents:
Graphics, PrinterSetup classes; Getting Started with Graphics topic