The text print project allows you to print simple text documents directly to printers or to a PDF or PostScript file.
To print a document in Gambas, you must:
The print process is executed in a local event loop and the Print method only returns when the print process has been completed or cancelled. During this local event loop, the following events are triggered one after the other:
Only the Draw event must be implemented. All other events are optional.
Begin() event
This event is triggered when the print process starts. You can define the Printer.Count property there if you know exactly how many pages you have to print. Otherwise, you must implement the Paginate() event to layout your document and calculate the number of pages. By default, only one page is printed. Other important parameters such as the paper format and resolution can also be set in this event.
Paginate() event
This event is triggered so that you can add a page number to your document in the background. If you handle this event, the event handler is called again and again until you explicitly define the Count property. The calculation of the number of pages depends on what exactly you are drawing. If you are drawing text, you can use the Paint.TextSize() or Paint.RichTextSize() methods to calculate the size of elements such as the text height.
Please note: The Paginate() event also has nothing to do with the actual drawing. This only happens in the Draw event, which is called once for each page.
Draw() event
This event is called once for each page that needs to be printed. The complete drawing is done with the Paint class. The current page number is returned by the Printer.Page property. Each time the Draw event is triggered, a new page is created on the printer - except for the first one, which is created automatically.
Event End()
This event is triggered when the printing process is complete. The Paint.Begin() method is automatically called shortly before the Printer.Begin event and the Paint.End() method shortly after the Printer.End event. You therefore do not need to call them explicitly.
Margins
A page is drawn within a rectangle whose origin is (0, 0) and has the values Paint.Width and Paint.Height. These sizes apply if the Printer.FullPage property has been set to True. You should always print with this setting. The following text print project shows you how to provide a text page with freely defined margins for all four page margins and how to use the paper format to define the rectangle within which printing takes place.
Coordinates
Instead of the drawing coordinates in dots, you can also use coordinates in millimetres. To do this, you must use the Paint.Scale(Sx, Sy) method to scale the coordinate system so that each coordinate you specify has the unit millimetres. You can also use the Paint.Translate(Tx, Ty) method to move the coordinate origin of the coordinate system as required. The x-axis points to the right, but the y-axis points downwards!
The following source code sections show you how to draw three geometric shapes (rectangle, circle and line) and text with a defined font on a sheet of A4 paper and specify all coordinates in millimetres:
' Gambas class file Private CurPrinter As Printer Private LeftMargin As Integer = 20 '-- Dimensions in millimetres Private TopMargin As Integer = 20 Private Rightmargin As Integer = 15 Private BottomMargin As Integer = 20 Public Sub Form_Open() CurPrinter = New Printer As "CurPrinter" CurPrinter.Paper = Printer.A4 CurPrinter.FullPage = True CurPrinter.GrayScale = False CurPrinter.Resolution = 300 End Public Sub btnPrint_Click() If CurPrinter.Configure() = False Then CurPrinter.Print() Endif End Public Sub CurPrinter_Begin() Paint.Scale(Paint.Width / CurPrinter.PaperWidth, Paint.Height / CurPrinter.PaperHeight) Paint.Translate(LeftMargin, TopMargin) Paint.FontScale = (1 / (Paint.Height / CurPrinter.PaperHeight)) End Public Sub CurPrinter_Draw() Dim curX, curY, curW, curH As Float Dim curPrintH, curPrintW As Float Dim curText As String Paint.AntiAlias = True Paint.Font = Font["Monospace,10"] '-- Print Str(Paint.Font.Size * 0.353) & " mm" curPrintH = CurPrinter.PaperHeight - TopMargin - BottomMargin curPrintW = CurPrinter.PaperWidth - LeftMargin – RightMargin '-- Drawing a red rectangle curW = CurPrinter.PaperWidth - LeftMargin - RightMargin Paint.DrawRect(0, 0, curW, 100, Color.Red, 0.1) '-- Drawing a black circle Paint.Arc(curW / 2, 50, 40, 0, 2 * Pi, False) Paint.Stroke() '-- Drawing text curText = "»»» Drucken mit Gambas" curX = 0 curY = 170 curH = Paint.Font.Size * 0.353 curW = CurPrinter.PaperWidth - LeftMargin - RightMargin Paint.DrawText(curText, curX, curY, curW, curH, Align.Center) '-- Draw a thin blue line Paint.Brush = Paint.Color(Color.Blue) '-- Line color Paint.MoveTo(0, curPrintH) '-- Starting point of the line Paint.LineTo(curPrintW, curPrintH) '-- End point of the line Paint.LineWidth = 0.1 '-- Line width Paint.Stroke() '-- Paint the line End Public Sub CurPrinter_End() '-- NOOP End
Printer dialogue
Call up the printer dialogue and start printing
If CurPrinter.Configure() = False Then CurPrinter.Print() Endif
from Gambas show some special features under QT that you need to be aware of:
Figure 23.6.1.1.1: Printer dialogue
Font sizes
The unit of the font size, as returned by the Paint.Font.Size property, is the typographic point. A typographic point is 1/72 of an inch (0.353 mm) in size. So if a 10-point font is a good size for drawing text on the screen, it may be too large for printing on paper: Since the resolution of the printer is much larger than that of the screen, you usually print everything smaller.
If you use methods such as Paint.Scale(…), Paint.Translate(…) or Paint.Rotate(…), the font size is changed according to the paint matrix:
[1] Public Sub CurPrinter_Draw() [2] [3] Paint.Font = Font["Monospace,10"] [4] ... [5] End [6] [7] Public Sub CurPrinter_Begin() [8] [9] Paint.Scale(Paint.Width / CurPrinter.PaperWidth, Paint.Height / CurPrinter.PaperHeight) [10] Paint.Translate(LeftMargin, TopMargin) [11] Paint.FontScale = (1 / (Paint.Height / CurPrinter.PaperHeight)) [12] [13] End
Please note: The instructions in lines 3 and 11 ensure that you print exactly with the set font!
The project, which is based on ideas from the author Claus Dietrich, enables you to print simple text documents directly on printers or to print and save the content of the text documents in a PDF or PostScript file.
Essential properties, methods and events of the Printer class (gb.qt4/5) are used.
Figure 23.6.1.1.2: Programme interface
The source text is displayed in full. Important procedures are then commented.
[1] ' Gambas class file [2] [3] Private $PrintFont As Font [4] Private $sFileName As String [5] Private $sCurText As String [6] Private $sCurFilePath As String [7] Private hPrinter As Printer [8] Private PageTexts As New String[] [9] [10] '-- All 6 of the following values have been tested in practice [11] Private LeftMargin As Integer = 20 ' In mm [12] Private Rightmargin As Integer = 15 [13] Private TopMargin As Integer = 15 [14] Private BottomMargin As Integer = 15 [15] Private HeaderMargin As Integer = 10 [16] Private FooterMargin As Integer = 10 [17] '----------------------------------- [18] [19] Private LMargin As Integer '-- In dots [20] Private TMargin As Integer [21] Private RMargin As Integer [22] Private BMargin As Integer [23] Private HMargin As Integer [24] Private FMargin As Integer [25] [26] [27] Public Sub Form_Open() [28] [29] Dim sMessage As String [30] [31] If Printer.List.Count = 0 Then ' True [32] sMessage = "<b><font size='+1', color='DarkRed'>" [33] sMessage &= ("PRINT MODE") [34] sMessage &= "</b></font><hr>" [35] sMessage &= "▶ " & ("No installed printer was detected.") & "<br>" [36] sMessage &= "▶ " & ("Printing to file only.") [37] Message.Error(sMessage) [38] cboxPrintToFile.Value = True [39] cboxPrintToFile.Enabled = False [40] Endif [41] [42] $PrintFont = Font["Liberation Mono,9"] '-- Default setting [43] bboxSetPrintFont.Text = $PrintFont.ToString() [44] [45] txtEditor.Font = Font["Monospace,12"] [46] txtEditor.Wrap = True [47] txtEditor.ShowLineNumber = True [48] txtEditor.ShowBraces = True [49] txtEditor.ShowCurrent = True [50] txtEditor.ShowPosition = True [51] [52] End [53] [54] Public Sub btnOpenText_Click() [55] [56] Dim sFilter As String [57] [58] lblFinish.Text = "" [59] [60] Dialog.Title = ("Select a plain-text file") [61] sFilter = "*.txt;*.html;*.sql;*.sh;*.js;*.css;*.c;*.c++;*.xml;*.class;*.webpage;*.gbs" [62] Dialog.Filter = [sFilter, ("Text files"), "*", ("All files")] [63] If Dialog.OpenFile(False) Then Return [64] $sCurFilePath = Dialog.Path [65] txtEditor.Text = File.Load(Dialog.Path) [66] $sCurText = txtEditor.Text [67] $sFileName = File.Name(Dialog.Path) [68] FMain.Caption = ("The text of the file is printed:") & " " & $sFileName [69] [70] End [71] [72] Public Sub txtEditor_Change() [73] $sCurText = txtEditor.Text [74] txtEditor.Save($sCurFilePath) [75] End [76] [77] Public Sub bboxSetPrintFont_Click() [78] [79] Dialog.Title = ("Select a print font") [80] Dialog.Font = Font["Liberation Mono,9"] '-- Default setting [81] If Dialog.SelectFont() Then Return [82] [83] $PrintFont = Dialog.Font [84] bboxSetPrintFont.Text = Dialog.Font.ToString() [85] [86] End [87] [88] Public Sub btnPrintText_Click() [89] [90] If $sCurText Then [91] lblFinish.Text = "" [92] With hPrinter = New Printer As "CurPrinter" [93] .Paper = Printer.A4 [94] .Resolution = 300 [95] .FullPage = True [96] End With [97] [98] If cboxPrintToFile.Value Then [99] Dialog.Title = ("Printing to file ...") [100] Dialog.Filter = ["*.pdf", "PDF file", "*.ps", "Post script file"] [101] Dialog.AutoExt = True [102] If Dialog.SaveFile() Then Return [103] hPrinter.OutputFile = Dialog.Path [104] hPrinter.Print() [105] Else [106] If hPrinter.Configure() = False Then [107] hPrinter.Print() [108] Endif [109] Endif [110] Endif [111] [112] End [113] [114] [115] Public Sub CurPrinter_Begin() [116] [117] Dim sFitPageText, sTextToPrint, sFullFitText As String [118] Dim hPaintExtents As PaintExtents [119] Dim iPages, curW, curH As Integer [120] [121] lblFinish.Text = "" [122] Paint.Font = $PrintFont [123] [124] LMargin = Paint.Width / hPrinter.PaperWidth * LeftMargin [125] TMargin = Paint.Width / hPrinter.PaperWidth * TopMargin [126] RMargin = Paint.Width / hPrinter.PaperWidth * RightMargin [127] BMargin = Paint.Width / hPrinter.PaperWidth * BottomMargin [128] [129] HMargin = Paint.Width / hPrinter.PaperWidth * HeaderMargin [130] FMargin = Paint.Width / hPrinter.PaperWidth * FooterMargin [131] [132] '-- Determine the number of pages - only possible via RichTextExtends [133] '-- TextExtends cannot be used [134] '-- Take not of the passed text, which converted to Rich-Text [135] curW = Paint.Width - LMargin - RMargin [136] hPaintExtents = Paint.RichTextExtents(Replace($sCurText, "\n", "<br>"), curW) [137] curH = Paint.Height - TMargin - HMargin - BMargin - FMargin [138] iPages = Ceil(hPaintExtents.Height / curH) + 1 '-- Add one page for safety [139] [140] '-- Generate a text which fits into the available width. Take note, that this text may have [141] '-- a lot of additional line breaks (LF)! The height is bigger than the number of expected [142] '-- pages to that the text fully fits into the avalable space. With this we get the full [143] '-- text with all addtional line-breaks. [144] [145] curW = Paint.W - LMargin - RMargin [146] curH = (Paint.H - TMargin - HMargin - BMargin - FMargin) * iPages [147] sFullFitText = Paint.TrimText($sCurText, curW, curH) [148] sTextToPrint = sFullFitText [149] [150] '-- Split the full text into separate pages [151] PageTexts.Clear() [152] Do [153] '-- Get the part of the text which fits in to one page [154] curW = Paint.W - LMargin - RMargin [155] curH = Paint.H - TMargin - HMargin - BMargin - FMargin [156] sFitPageText = Paint.TrimText(sTextToPrint, CurW, CurH) [157] '-- Add the text the PageTexts-Array [158] PageTexts.Add(sFitPageText) [159] '-- Cut the last page out of the full text [160] sTextToPrint = String.Right$(sTextToPrint, -String.Len(sFitPageText)) [161] '-- Repeat this until nothing is left to print [162] Loop Until sTextToPrint = "" [163] [164] '-- Set the total number of pages [165] hPrinter.Count = PageTexts.Count [166] [167] End [168] [169] Public Sub CurPrinter_Draw() [170] [171] Dim curX, curY, curW, curH As Integer [172] Dim sPrintText As String [173] [174] '-- HEADER-TEXT [175] Paint.Font = Font["Liberation Mono,9"] [176] curX = LMargin [177] curY = TMargin [178] curW = Paint.W - LMargin - RMargin [179] curH = HMargin [180] sPrintText = $sFileName [181] Paint.DrawText(sPrintText, curX, curY, curW, curH, Align.TopLeft) [182] sPrintText = Format(Now, "dddd - dd.mm.yyyy") [183] Paint.DrawText(sPrintText, curX, curY, curW, curH, Align.TopRight) [184] [185] '-- HEADER-LINE [186] curX = LMargin [187] curY = TMargin + (Paint.Width / hPrinter.PaperWidth) * 3.8 '-- mm [188] curW = Paint.W - RMargin [189] Paint.MoveTo(curX, curY) '-- Starting point of the line [190] Paint.LineTo(curW, curY) '-- End point of the line [191] Paint.LineWidth = 0.1 '-- Line width [192] Paint.Stroke() '-- Paint the line [193] [194] '-- CONTENT [195] '-- If the text fits the requested rectangle, it is returned as is. [196] '-- Otherwise it is trimmed and followed by an ellipsis character so that it fits. [197] '-- Remove "…" if found at the end of a page [198] If String.Right$(PageTexts[hPrinter.Page - 1], 1) = "…" Then [199] PageTexts[hPrinter.Page - 1] = String.Left$(PageTexts[hPrinter.Page - 1], -1) [200] Endif [201] Paint.Font = $PrintFont [202] curX = LMargin [203] curY = TMargin + HMargin [204] curW = Paint.W - LMargin - RMargin [205] curH = Paint.H - TMargin - HMargin - BMargin - FMargin [206] sPrintText = PageTexts[hPrinter.Page - 1] [207] Paint.DrawText(sPrintText, curX, curY, curW, curH) [208] [209] '-- FOOTER-LINE [210] curX = LMargin [211] curY = Paint.H - BMargin - (Paint.Width / hPrinter.PaperWidth) * 4.0 '-- mm [212] curW = Paint.W - RMargin [213] Paint.MoveTo(curX, curY) '-- Starting point of the line [214] Paint.LineTo(curW, curY) '-- End point of the line [215] Paint.LineWidth = 0.1 '-- Line width [216] Paint.Stroke() '-- Paint the line [217] [218] '-- FOOTER-TEXT [219] Paint.Font = Font["Liberation Mono,9"] [220] curX = LMargin [221] curY = Paint.H - FMargin - BMargin [222] curW = Paint.W - LMargin - RMargin [223] curH = HMargin [224] [225] sPrintText = ("Page") & " " & hPrinter.Page & " " & ("of") & " " & hPrinter.Count [226] Paint.DrawText(sPrintText, curX, curY, curW, curH, Align.BottomRight) [227] [228] End [229] [230] Public Sub CurPrinter_End() [231] lblFinish.Alignment = Align.Center [232] lblFinish.Text = " ▶ " & ("The text has been printed successfully!") [233] End [234] [235] Public Sub Form_Close() [236] [237] Dim hWindow As Window [238] [239] '-- Close all open windows [240] For Each hWindow In Windows [241] hWindow.Close() [242] Next [243] [244] End
Comment