Reputation: 65
I am having a terrible time trying to allow the user to set the margins for a report. Right now I have it hard coded but I would prefer to set them at run time so they can be changed. I tried this:
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
Me.OriginAtMargins = True
Me.DefaultPageSettings.Margins = New Margins(25, 25, 25, 25)
End Sub
To print a 1/4" margin which is well beyond the printer's hard margins. Nothing prints. According to Margins the arguments are in hundreds of an inch. If I change the code to:
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
Me.OriginAtMargins = True
Me.DefaultPageSettings.Margins = New Margins(20, 20, 23, 23)
End Sub
But when I change the code to:
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
Me.OriginAtMargins = True
Me.DefaultPageSettings.Margins = New Margins(21, 20, 23, 23)
End Sub
This is what I get, which makes no sense. It looks like it shifts over 1 inch:
And I am not the only one having problems with margins, there is no response here and I even posted to microsoft, with no response.
Since report writers can produce the majority of documents I will presume not many people use the PrintDocument object. So I am seeing what anyone here has to say before I report a bug to Microsoft, which will take a considerable time for a response to come from then.
EDIT: I made a simpler version and got similar but still strange results. I had to leave a lot of the code in the class, class definitions, properties, ect. that the caller requires. I just removed (almost) all the code from the events.
Here is the event code:
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
Me.OriginAtMargins = True
Me.DefaultPageSettings.Margins = New Margins(19, 20, 23, 23)
mintLevel = 0
'Reset the loop trackers (used when we need to break out to print a page but remember our place) and others.
mintRowLoopStart = 0
mintTableLoopStart = 0
'Flags
ResetHeaderFooterFlags()
'Page counters
mintCurrentPage = 0
mintTotalPages = 0
End Sub
Private Sub rotHCReport_QueryPageSettings(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles Me.QueryPageSettings
e.PageSettings.Landscape = mePageOrientation = Orientation.Landscape
mintCurrentPage += 1
End Sub
Private Sub rotHCReport_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles Me.PrintPage
Dim DR As DataRow
Dim PrintFont As Font
e.Graphics.PageUnit = GraphicsUnit.Inch
PrintFont = New Font("Arial", 8, FontStyle.Regular)
For intRow = 0 To 10
DR = mDS.Tables(0).Rows(intRow)
For intColumn = 0 To 5
e.Graphics.DrawString(DR(intColumn).ToString, PrintFont, New SolidBrush(Color.Black), intColumn + 1, CSng(intRow + 1))
Next
Next
End Sub
Private Sub rotHCReport_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.EndPrint
mbSetUpRequired = True
End Sub
Which produces (looks less than 1/8 of an inch):
And changing:
Me.DefaultPageSettings.Margins = New Margins(20, 20, 23, 23)
Produces (looks more than 1/4 inch):
EDIT2: I tried TnTinMn's technique and I had a difficult time understanding the TranslateTransform method. From my testing it almost sounds like it "adds" to whatever margin you have. Worse, if I use 0 I get a larger margin than what I have set, OriginAtMargins makes no difference at this point. What I am trying to do is create a consistent margin across printers.
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
'Me.OriginAtMargins = True
Me.DefaultPageSettings.Margins = New Margins(25, 25, 25, 25)
'Subreport level
mintLevel = 0
'Reset the loop trackers (used when we need to break out to print a page but remember our place) and others.
mintRowLoopStart = 0
mintTableLoopStart = 0
'Flags
ResetHeaderFooterFlags()
'Page counters
mintCurrentPage = 0
mintTotalPages = 0
End Sub
Private Sub rotHCReport_QueryPageSettings(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles Me.QueryPageSettings
e.PageSettings.Landscape = mePageOrientation = Orientation.Landscape
mintCurrentPage += 1
End Sub
Private Sub rotHCReport_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles Me.PrintPage
Dim DR As DataRow
Dim PrintFont As Font
e.Graphics.PageUnit = GraphicsUnit.Inch
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform(e.MarginBounds.X / 100.0F, e.MarginBounds.Y / 100.0F)
PrintFont = New Font("Arial", 8, FontStyle.Regular)
For intRow = 0 To 10
DR = mDS.Tables(0).Rows(intRow)
For intColumn = 0 To 5
e.Graphics.DrawString(DR(intColumn).ToString, PrintFont, New SolidBrush(Color.Black), CSng(intColumn + 1), CSng(intRow + 1))
Next
Next
End Sub
Private Sub rotHCReport_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.EndPrint
mbSetUpRequired = True
End Sub
I can change the TranslateTransform call to this:
e.Graphics.TranslateTransform(-e.MarginBounds.X / 100.0F, -e.MarginBounds.Y / 100.0F)
Which produces this, better, but I already have a hack job working. I am trying to figure out how to do this right.
It seems a great mystery on how to use the PrintDocument properly.
TnTinMn is using the PrintController while I am using the PrintDocument. I tried incorporating his proposed change and it did not work at all. Any idea how to get these two object to work together?
Public Class NewController
Inherits PrintController
Public Overrides Function OnStartPage(ByVal document As System.Drawing.Printing.PrintDocument, ByVal e As System.Drawing.Printing.PrintPageEventArgs) As System.Drawing.Graphics
Dim g As System.Drawing.Graphics
g = MyBase.OnStartPage(document, e)
g.PageUnit = GraphicsUnit.Inch
g.ResetTransform()
g.TranslateTransform((e.MarginBounds.X - e.PageSettings.HardMarginX) / 100.0F, (e.MarginBounds.Y - e.PageSettings.HardMarginY) / 100.0F)
'This does not work either
'e.Graphics.PageUnit = GraphicsUnit.Inch
'e.Graphics.ResetTransform()
'e.Graphics.TranslateTransform((e.MarginBounds.X - e.PageSettings.HardMarginX) / 100.0F, (e.MarginBounds.Y - e.PageSettings.HardMarginY) / 100.0F)
'Return e.Graphics
Return g
End Function
End Class
And I changed the other class.
Private mPC As NewController
Public Sub New()
MyBase.New()
mPC = New NewController
Me.PrintController = mPC
End Sub
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
Me.DefaultPageSettings.Margins = New Margins(25, 25, 25, 25)
'Subreport level
mintLevel = 0
'Reset the loop trackers (used when we need to break out to print a page but remember our place) and others.
mintRowLoopStart = 0
mintTableLoopStart = 0
'Flags
ResetHeaderFooterFlags()
'Page counters
mintCurrentPage = 0
mintTotalPages = 0
End Sub
'Raised before each and every page
Private Sub rotHCReport_QueryPageSettings(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles Me.QueryPageSettings
e.PageSettings.Landscape = mePageOrientation = Orientation.Landscape
mintCurrentPage += 1
End Sub
Private Sub rotHCReport_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles Me.PrintPage
Dim DR As DataRow
Dim PrintFont As Font
e.Graphics.PageUnit = GraphicsUnit.Inch
PrintFont = New Font("Arial", 8, FontStyle.Regular)
For intRow = 0 To 10
DR = mDS.Tables(0).Rows(intRow)
For intColumn = 0 To 5
e.Graphics.DrawString(DR(intColumn).ToString, PrintFont, New SolidBrush(Color.Black), CSng(intColumn + 1), CSng(intRow + 1))
'millimetersd
'e.Graphics.DrawString(DR(intColumn).ToString, PrintFont, New SolidBrush(Color.Black), CSng((intColumn + 1) * 25.4), CSng((intRow + 1) * 25.4))
Next
Next
End Sub
Private Sub rotHCReport_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.EndPrint
mbSetUpRequired = True
End Sub
Same results.
EDIT FINAL: TnTinMn's solution worked perfectly. I think I made an error somewhere copying the code between here, my test dll and production dll. In any event, I went over everything again, albeit a little more carefully and it worked. Here is the code that worked in test (and the same technique worked in production)
Private Sub rotHCReport_BeginPrint(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.BeginPrint
'Me.OriginAtMargins = True 'Don't need this anymore
Me.DefaultPageSettings.Margins = New Margins(25, 25, 25, 25) 'These are the margins actually used
'Subreport level
mintLevel = 0
'Reset the loop trackers (used when we need to break out to print a page but remember our place) and others.
mintRowLoopStart = 0
mintTableLoopStart = 0
'Flags
ResetHeaderFooterFlags()
'Page counters
mintCurrentPage = 0
mintTotalPages = 0
End Sub
'Raised before each and every page
Private Sub rotHCReport_QueryPageSettings(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.QueryPageSettingsEventArgs) Handles Me.QueryPageSettings
e.PageSettings.Landscape = mePageOrientation = Orientation.Landscape
mintCurrentPage += 1
End Sub
Private Sub rotHCReport_PrintPage(ByVal sender As Object, _
ByVal e As System.Drawing.Printing.PrintPageEventArgs) Handles Me.PrintPage
Dim DR As DataRow
Dim PrintFont As Font
e.Graphics.PageUnit = GraphicsUnit.Inch
e.Graphics.ResetTransform()
e.Graphics.TranslateTransform((e.MarginBounds.X - e.PageSettings.HardMarginX) / 100.0F, (e.MarginBounds.Y - e.PageSettings.HardMarginY) / 100.0F)
PrintFont = New Font("Arial", 8, FontStyle.Regular)
For intRow = 0 To 10
DR = mDS.Tables(0).Rows(intRow)
For intColumn = 0 To 5
e.Graphics.DrawString(DR(intColumn).ToString, PrintFont, New SolidBrush(Color.Black), CSng(0.25 + intColumn), CSng(0.25 + intRow))
Next
Next
End Sub
Private Sub rotHCReport_EndPrint(ByVal sender As Object, ByVal e As System.Drawing.Printing.PrintEventArgs) Handles Me.EndPrint
mbSetUpRequired = True
End Sub
I set 1/4" margins and I got 1/4" margins! Here's my 7th screenshot, lucky #7.
Upvotes: 4
Views: 10168
Reputation: 11801
In your PrintPage
handler, you have the statement e.Graphics.PageUnit = GraphicsUnit.Inch
and are thus causing the problem. The received e.Graphics.PageUnit
is set to Display
and the Graphics has a coordinate transform applied to it that reflects your OriginAtMargins = True
setting. The transforms' OffsetX
and OffsetY
values were computed using the Display
PageUnit
setting (in 1/100 inch). When you change the PageUnit
to Inch
those offsets are now interpreted as Inches and whatever you are drawing on the Graphics is drawn out of bounds. This is why you get an empty page.
You should be able to eliminate the OriginAtMargins = True
statement and modify the PrintPage
handler code like this:
e.Graphics.PageUnit = GraphicsUnit.Inch
e.Graphics.ResetTransform() ' clear any previous transforms
e.Graphics.TranslateTransform((e.MarginBounds.X - e.PageSettings.HardMarginX) / 100.0F, (e.MarginBounds.X - e.PageSettings.HardMarginY) / 100.0F)
Edit: I corrected the TranslateTransform arguments to account for the printer's hard margin values that I originally neglected. This is based on the transform performed by the StandardPrintController.OnStartPage method when then PrintDocument.OriginAtMargins
property is true.
Upvotes: 4