Table of Contents

The text print project allows you to print simple text documents directly to printers or to a PDF or PostScript file.

23.6.1.1.1 Preliminary remarks - Notes

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:

BILD 1

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!

23.6.1.1.2 Text printing project

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.

BILD 2

Figure 23.6.1.1.2: Programme interface

23.6.1.1.3 Text print project: Source text

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

Download