Link to home
Create AccountLog in
Avatar of thearniec
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?
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

Open in new window

Avatar of vigylant
vigylant

You could try the TextRenderer class :)
Example:
 
TextRenderer.DrawText(e.Graphics, "Regular Text", Me.Font, New Point(10, 10), SystemColors.ControlText)

Open in new window

Avatar of Nasir Razzaq
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.
Avatar of thearniec

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.  
Where do you get the text from? Are you sure it contains carriage returns?
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.
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.keychar)) 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.
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?
There is a paid solution. DeveloperExpress.
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
Avatar of thearniec
thearniec

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer