I had previously used a RichTextBox and the SelPrint routine, but I discovered that routine would not work with an InkEdit Control. With the help of jpbro, we put together a routine for the InkEdit Control (located in the parent forum). But that routine does not work with a Textbox, and I could not find anything online to fit the bill. So I came up with the routine attached.
This routine has experienced very little testing because my development computer does not currently have access to an actual printer. Bug reports would be appreciated.
I had previously used a RichTextBox and the SelPrint routine, but I discovered that routine would not work with an InkEdit Control. With the help of jpbro, we put together a routine for the InkEdit Control (located in the parent forum). But that routine does not work with a Textbox, and I could not find anything online to fit the bill. So I came up with the routine attached.
This routine has experienced very little testing because my development computer does not currently have access to an actual printer. Bug reports would be appreciated.
J.A. Coutts
I think you're too easy. This parable. Is the length of the text larger than the width of the paper? Whether the page turn should be related to text font height.
You set 120 characters per line. If the font size changes, you cannot display 120 characters. Need to recalculate. and if set newpage, you must think about font size height.
Actually, with a FontSze of 10, the characters per line work out to 78 on my printer using an 8.5 inch page. But to be flexible, one should allow for different size fonts. Replace the CharPerLine function with:
and move it after setting the font size. This only works for Truetype fonts that have a fixed width. As far the character height is concerned, that should not matter. When it gets to the bottom of the page that I have defined, it calls for a new page.
Private Sub PrintWrappedText(ByVal txt As String, ByVal indent As Single, ByVal left_margin As Single, ByVal top_margin As Single, ByVal right_margin As Single, ByVal bottom_margin As Single)
' Print a string on a Printer or PictureBox, wrapped within the margins.
Dim next_paragraph As String
Dim next_word As String
Dim pos As Integer
' Start at the top of the page.
Printer.CurrentY = top_margin
' Repeat until the text is all printed.
Do While Len(txt) > 0
' Get the next paragraph.
pos = InStr(txt, vbCrLf)
If pos = 0 Then
' Use the rest of the text.
next_paragraph = Trim$(txt)
txt = ""
Else
' Get the paragraph.
next_paragraph = Trim$(Left$(txt, pos - 1))
txt = Mid$(txt, pos + Len(vbCrLf))
End If
' Indent the paragraph.
Printer.CurrentX = left_margin + indent
' Print the paragraph.
Do While Len(next_paragraph) > 0
' Get the next word.
pos = InStr(next_paragraph, " ")
If pos = 0 Then
' Use the rest of the paragraph.
next_word = next_paragraph
next_paragraph = ""
Else
' Get the word.
next_word = Left$(next_paragraph, pos - 1)
next_paragraph = Trim$(Mid$(next_paragraph, pos + 1))
End If
' See if there is room for this word.
If Printer.CurrentX + Printer.TextWidth(next_word) _
> right_margin _
Then
' It won't fit. Start a new line.
Printer.Print
Printer.CurrentX = left_margin
' See if we have room for a new line.
If Printer.CurrentY + Printer.TextHeight(next_word) _
> bottom_margin _
Then
' Start a new page.
Printer.NewPage
Printer.CurrentX = left_margin
Printer.CurrentY = top_margin
End If
End If
' Now print the word. The ; makes the
' Printer not move to the next line.
Printer.Print next_word & " ";
Loop
' Finish the paragraph by ending the line.
Printer.Print
Loop
End Sub
The DrawText API may be of interest, it allows placement and measurement of text within specified margins and copes with TrueType fonts.
Example of use which may give you some ideas;
Code:
Private Const DT_CENTER = &H1
Private Const DT_WORDBREAK = &H10
Private Const DT_CALCRECT = &H400
'Type RECT is declared Public elsewhere in a module
Friend Function DrawTextInaBox(Pdev As Object, str2Print$, BoxUser As RECT, Optional IncludeBox As Boolean, Optional FillColor&, Optional BorderColor&)
'Pdev PrintDevice is a Form, Picture or Printer
'Str2Print$ is the sting to print
'BoxUser is the Rectangle in which to print the text
'IncludeBox if True a coloured rectangle is placed behind the text
'FillColor and BorderColour are applied to IncludeBox if it is specified
'BoxUser is specified in terms of the Scalemode (including vbUser) coordinates prevailing on Pdev
Dim BoxPixels As RECT
Dim sFillStyle, sFillColor, h, x, y
With Pdev
'convert BoxUser rectangle specified in units of Pdev.ScaleMode into BoxPixels
BoxPixels.Left = .ScaleX(BoxUser.Left - .ScaleLeft, .ScaleMode, vbPixels)
BoxPixels.Top = .ScaleY(BoxUser.Top - .ScaleTop, .ScaleMode, vbPixels)
BoxPixels.Right = .ScaleX(BoxUser.Right - .ScaleLeft, .ScaleMode, vbPixels)
BoxPixels.Bottom = .ScaleY(BoxUser.Bottom - .ScaleTop, .ScaleMode, vbPixels)
If IncludeBox Then
sFillStyle = .FillStyle
sFillColor = .FillColor
x = .CurrentX: y = .CurrentY
'measure height of box required and return in h
h = DrawText(.hdc, str2Print$, -1, BoxPixels, DT_WORDBREAK Or DT_CALCRECT)
'draw a filled box of the correct height
.FillStyle = vbFSSolid
.FillColor = FillColor&
'the border consumes 1 pixel inside the rectangle specified
'draw the box a little larger than specified on the left to ensure there is a pixel between text and the left border, the other borders are better behaved
Pdev.Line (BoxUser.Left - .ScaleX(.DrawWidth + 1, vbPixels, .ScaleMode), BoxUser.Top)-(BoxUser.Right, BoxUser.Top + .ScaleY(h + .DrawWidth, vbPixels, .ScaleMode)), BorderColor&, B
.CurrentX = x: .CurrentY = y
.FillStyle = sFillStyle
.FillColor = sFillColor
End If
DrawText .hdc, str2Print$, -1, BoxPixels, DT_WORDBREAK
End With
End Function