User Tools

Site Tools


Sidebar

Multimedia

k23:k23.6:k23.6.1:k23.6.1.1:start

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:

  • first create a new Printer object,
  • then call the Printer.Configure() method, which displays a printer configuration dialogue,
  • then start the printing process by calling the Printer.Print() method and
  • then draw the document page by page with Paint.

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:

  • Printer.Begin(),
    • Printer.Paginate(),
    • Printer.Draw() and
  • Printer.End().

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

  • The Properties> Pages> Orientation setting is adopted and realised when printing. The paper format is not adopted.
  • In contrast, the Properties> Pages> Margins settings are ignored when printing because there appears to be no communication between the print dialogue and the Printer class.
  • You can set the resolution (unit dpi) for direct printing under Properties> Advanced> General> Resolution. However, in the authors' experience, this setting in the printer dialogue does not change the definition Printer.Resolution = xy in the source text!

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.

  • You can select the file to be printed in a file selection dialogue and display the text in a text editor:

BILD 2

Figure 23.6.1.1.2: Programme interface

  • You can change the text before printing. The changes are saved in the selected text file.
  • It is printed on a DIN A4 page. The page format can only be changed in the source text.
  • The text margins are predefined with fixed values, which have proven to be practical.
  • However, you can change the pre-set print font in a font selection dialogue.
  • Continuous text sections in the text are wrapped depending on the page margins and the specified print font. Hyphenation does not take place.
  • Page numbering is not carried out using the paginate event, but by determining the total number of pages to be printed before printing.
  • A print page contains a header with the name of the print file and the print date, followed by the page text content after a separator line. Each print page has a footer in which the current page number and the number of all print pages are displayed under a line in the format 'Page x of y'.

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

  • Lines 31 to 50 first check whether a printer is installed in the system, then the default font for the font selection dialogue is also specified. Finally, the essential properties of the editor for displaying the content of the selected text file are determined.
  • You can select the file to be printed in a file selection dialogue in lines 60 to 68.
  • You can change the set print font in lines 77 to 86 in a font selection dialogue.
  • A new printer object is first created and configured in lines 88 to 112. If printing to a file has been activated, the text is 'printed' to a file. Otherwise, a dialogue for configuring a printer is called up and then the printout is started with the hPrinter.Print() method. The method returns False if the printout was successful.
  • In the CurPrinter_Begin() event handling in lines 115 to 167, the margins are first converted from millimetres to XY (lines 124 to 133). Then the number of pages to be printed is calculated depending on the printable width and the specified print font.
  • The individual pages are drawn in the curPrinter_Draw() event handling in lines 169 to 228. Anyone who works with Paint will notice this: The dedicated definition of curX, curY, curW, curH or curText before each drawing - primarily of text - is a good way to visualise exactly the rectangle that forms the container in which you want to draw the text.
  • First, in lines 174 to 192 on each page, a header is drawn with the name of the print file (left-aligned) and the print date (right-aligned) as well as a separator line underneath.
  • This is followed by the page text with the page number changed in each case, which is drawn in lines 194 to 207.
  • Finally, a footer with the current page number and the number of all printed pages in the format 'Page x of y' is drawn in lines 209 to 226 on each page, flush right under a separator line.

Download

The website uses a temporary session cookie. This technically necessary cookie is deleted when the browser is closed. You can find information on cookies in our privacy policy.
k23/k23.6/k23.6.1/k23.6.1.1/start.txt · Last modified: 09.03.2024 by emma

Page Tools