thearniec
asked on
Problem with linespacing on Graphics.Drawstring
Still working on getting formatted output. I have a routine using the Graphics.Drawstring method from the PrintPage EventArgs class in VB.NET printing output to a printer, and it works perfectly for single-line text fields, etc.
However, when dealing with multi-line text fields where the users could insert carriage returns, and my need to insert manual line breaks, is not working. I end up printing all lines on top of each other.
I've developed branching logic to search for VBCR in the field, and to go down a line for it but not print it. I've also included logic to look for logical line breaks in the field.
I'm sure this is a simple logic error but in the past 4 hours of stepping through my code I'm not seeing where the problem lies. Anyone see?
However, when dealing with multi-line text fields where the users could insert carriage returns, and my need to insert manual line breaks, is not working. I end up printing all lines on top of each other.
I've developed branching logic to search for VBCR in the field, and to go down a line for it but not print it. I've also included logic to look for logical line breaks in the field.
I'm sure this is a simple logic error but in the past 4 hours of stepping through my code I'm not seeing where the problem lies. Anyone see?
Private Sub PrintPage(ByVal sender As Object, ByVal ev As PrintPageEventArgs)
Try
Dim yPos As Single = 100
Dim leftMargin As Single = ev.MarginBounds.Left
Dim topMargin As Single = ev.MarginBounds.Top
Dim drawBoldFont As New Font("Arial", 10, FontStyle.bold)
Dim drawFont As New Font("Arial", 10)
Dim lines as single = 17
Dim spaces as single = 7
Dim header as string
Dim x as integer
dim linesToSkip as integer
'Add the page heading and the time submitted
ev.Graphics.DrawString("THE FOLLOWING REQUEST HAS BEEN SUBMITTED", drawBoldFont, Brushes.Black, leftMargin, yPos, New StringFormat())
yPos = yPos + (2*lines)
header = "Department: "
ev.Graphics.DrawString(header, drawBoldFont, Brushes.Black, leftMargin, yPos, New StringFormat())
ev.Graphics.DrawString(Me.txtDepartment.Text.Trim, drawFont, Brushes.Black, leftMargin+(len(header)*spaces), yPos, New StringFormat())
yPos = yPos + (1*lines)
header = "Contact Name: "
ev.Graphics.DrawString(header, drawBoldFont, Brushes.Black, leftMargin, yPos, New StringFormat())
ev.Graphics.DrawString(Me.txtContact.Text.Trim, drawFont, Brushes.Black, leftMargin+(len(header)*spaces), yPos, New StringFormat())
yPos = yPos + (1*lines)
header = "Phone: "
ev.Graphics.DrawString(header, drawBoldFont, Brushes.Black, leftMargin, yPos, New StringFormat())
ev.Graphics.DrawString(Me.txtPhone.Text.Trim, drawFont, Brushes.Black, leftMargin+(len(header)*spaces), yPos, New StringFormat())
yPos = yPos + (2*lines)
'*********All of the above work fine, but when I start getting to the multi-line field below it breaks up
header = "Message: "
ev.Graphics.DrawString(header, drawBoldFont, Brushes.Black, leftMargin, yPos, New StringFormat())
x = 1
linesToSkip = 1
dim currentChar As Integer
dim currentLine As Integer
currentChar = 0
currentLine = 1
Dim chars As Integer
Dim foundLineReturn As Boolean
While currentChar < Me.txtMenu.Text.Length
chars = 0
foundLineReturn = False
While chars < 80
If Me.txtMenu.Text.Substring(currentChar + chars, 1) = vbCr Then
foundLineReturn = True
If chars > 1 Then
If currentLine = 1 Then
ev.Graphics.DrawString(Me.txtMenu.Text.Substring(currentChar, chars), drawFont, Brushes.Black, leftMargin + (Len(header) * spaces), yPos, New StringFormat())
Else
ev.Graphics.DrawString(Me.txtMenu.Text.Substring(currentChar, chars), drawFont, Brushes.Black, leftMargin, yPos, New StringFormat())
End If
End If
yPos = yPos + (2 * lines)
chars += 1
currentChar = currentChar + chars
Exit While
Else
chars += 1
End If
End While
If foundLineReturn = False Then
If Me.txtMenu.Text.Substring(currentChar + chars, 1) <> " " And _
Me.txtMenu.Text.Substring(currentChar + chars, 1) <> "-" And _
Me.txtMenu.Text.Substring(currentChar + chars, 1) <> vbLf Then
' As long as the last character is not space or carriage return,
' keep subtracting another character from the text to be printed.
chars = 80
If currentLine = 1 Then chars = chars - 20
While chars > 0 AndAlso _
Me.txtMenu.Text.Substring(currentChar + chars, 1) <> " " AndAlso _
Me.txtMenu.Text.Substring(currentChar + chars, 1) <> vbLf
chars -= 1
End While
chars += 1
End If
If chars = 0 Or chars = 1 Then chars = 80
If currentLine = 1 Then
ev.Graphics.DrawString(Me.txtMenu.Text.Substring(currentChar, chars), drawFont, Brushes.Black, leftMargin + (Len(header) * spaces), yPos, New StringFormat())
Else
ev.Graphics.DrawString(Me.txtMenu.Text.Substring(currentChar, chars), drawFont, Brushes.Black, leftMargin, yPos, New StringFormat())
End If
currentChar = currentChar + chars
currentLine += 1
yPos = yPos + (1 * lines)
End If
End While
yPos = yPos + (1 * lines)
'additionally none of the below prints either
yPos = yPos + (2*lines)
header = "Sent: "
ev.Graphics.DrawString(header, drawBoldFont, Brushes.Black, leftMargin, yPos, New StringFormat())
ev.Graphics.DrawString(Now.ToShortDateString & " - " & Now.ToShortTimeString, drawFont, Brushes.Black, leftMargin+(len(header)*spaces), yPos, New StringFormat())
yPos = yPos + (2*lines)
Catch ex As Exception
HandleError("Error in escort request form PrintPage routine: " & ex.Message, "PrintPage")
End Try
End Sub
If stepping through the code, it turns out that the logic is working correctly and the conditions are working as they should, then you may want to use the measurestring function to determine how much space a text would take on page.
ASKER
I'm sorry guys, I must be dense today. I've done some googles of TextRenderer.drawText and I'm finding it works about the same as Graphics.DrawString. Does DrawText automatically insert line breaks?
And CodeCruiser, I'm not sure how MeasureString will help given my code, because I am moving the Y Coordinate in the code but what happens is the first line and second line of a multi-line text field print on top of each other for some reason. Paragraphs are spread apart. I THINK the problem is that a carriage return is printing with one line moving it down but I've tried filtering out VBCR, VBCRLF, VBLF, and I'm getting the same results.
And CodeCruiser, I'm not sure how MeasureString will help given my code, because I am moving the Y Coordinate in the code but what happens is the first line and second line of a multi-line text field print on top of each other for some reason. Paragraphs are spread apart. I THINK the problem is that a carriage return is printing with one line moving it down but I've tried filtering out VBCR, VBCRLF, VBLF, and I'm getting the same results.
Where do you get the text from? Are you sure it contains carriage returns?
ASKER
CC: The text is a user text field, much like I'm typing in right now with the Post Comment/solution field here on EE.com. It is used for a user to enter an order, and it seems likely that many users will choose to put one item per line in this field. As such, I am trying to code it so it CAN contain carriage returns, but it does not have to.
Thanks agian for your help with this...I truly appreciate it.
Thanks agian for your help with this...I truly appreciate it.
The MeasureString would come in handy if there is no carriage return in the text. You could use this function to determine whether you need to add a line break or draw it on single line.
You could put a messagebox.show(asc(e.keyc har)) in the keypress event of textbox where the input is being provided to determine what asc code is added for enter key and use that to find line breaks.
You could put a messagebox.show(asc(e.keyc
ASKER
Well I checked, it is VBCR being used, which I was checking for.
I'm still thinking the code I have above SHOULD work, and that I have a logic error that I can't find.
But beyond that, I cannot imagine that I'm the only one trying to print a multi-line textfield to a printer. Are there no classes or basic code that can do what I'm trying?
I'm still thinking the code I have above SHOULD work, and that I have a logic error that I can't find.
But beyond that, I cannot imagine that I'm the only one trying to print a multi-line textfield to a printer. Are there no classes or basic code that can do what I'm trying?
There is a paid solution. DeveloperExpress.
ASKER
Been workin gat this for 2 more hours this morning...still no go. Anything else that does not include buying Devleoper Express?
ASKER CERTIFIED SOLUTION
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
Open in new window