我Graphics.ScaleTransform
用来拉伸文本行,使它们适合页面的宽度,然后打印该页面。但是,这会将打印作业转换为位图 - 对于具有许多页面的打印,这会导致打印作业的大小上升到令人讨厌的比例,并极大地减慢打印速度。
如果我不这样缩放,打印作业仍然非常小,因为它只是向打印机发送文本打印命令。
Graphics.ScaleTransform
我的问题是,除了使用拉伸文本的宽度之外,还有其他方法吗?
下面是演示这一点的示例代码(将被调用Print.Test(True)
并Print.Test(False)
显示缩放对打印作业的影响):
Imports System.Drawing
Imports System.Drawing.Printing
Imports System.Drawing.Imaging
Public Class Print
Dim FixedFont As Font
Dim Area As RectangleF
Dim CharHeight As Double
Dim CharWidth As Double
Dim Scale As Boolean
Const CharsAcross = 80
Const CharsDown = 66
Const TestString = "!""#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
Private Sub PagePrinter(ByVal sender As Object, ByVal e As PrintPageEventArgs)
Dim G As Graphics = e.Graphics
If Scale Then
Dim ws = Area.Width / G.MeasureString(Space(CharsAcross).Replace(" ", "X"), FixedFont).Width
G.ScaleTransform(ws, 1)
End If
For CurrentLine = 1 To CharsDown
G.DrawString(Mid(TestString & TestString & TestString, CurrentLine, CharsAcross), FixedFont, Brushes.Black, 0, Convert.ToSingle(CharHeight * (CurrentLine - 1)))
Next
e.HasMorePages = False
End Sub
Public Shared Sub Test(ByVal Scale As Boolean)
Dim OutputDocument As New PrintDocument
With OutputDocument
Dim DP As New Print
.PrintController = New StandardPrintController
.DefaultPageSettings.Landscape = False
DP.Area = .DefaultPageSettings.PrintableArea
DP.CharHeight = DP.Area.Height / CharsDown
DP.CharWidth = DP.Area.Width / CharsAcross
DP.Scale = Scale
DP.FixedFont = New Font("Courier New", DP.CharHeight / 100, FontStyle.Regular, GraphicsUnit.Inch)
.DocumentName = "Test print (with" & IIf(Scale, "", "out") & " scaling)"
AddHandler .PrintPage, AddressOf DP.PagePrinter
.Print()
End With
End Sub
End Class
更新:我改为使用与 GDI 调用的互操作。这是相关代码;GDI 类充满了我从http://pinvoke.net/的 wiki 复制的相关函数和常量的定义。
' convert from Graphics units (100 dpi) to device units
Dim GDIMappedCharHeight As Double = CharHeight * G.DpiY / 100
Dim GDIMappedCharWidth As Double = CharWidth * G.DpiX / 100
Dim FixedFontGDI As IntPtr = GDI.CreateFont(GDIMappedCharHeight, GDIMappedCharWidth, 0, 0, 0, 0, 0, 0, GDI.DEFAULT_CHARSET, GDI.OUT_DEFAULT_PRECIS, GDI.CLIP_DEFAULT_PRECIS, GDI.DEFAULT_QUALITY, GDI.FIXED_PITCH, "Courier New")
Dim CharRect As New GDI.STRUCT_RECT
Dim hdc As IntPtr = G.GetHdc()
GDI.SelectObject(hdc, FixedFontGDI)
' I used SetBkMode transparent as my text needed to overlay a background
GDI.SetBkMode(hdc, GDI.TRANSPARENT)
' draw it character by character to get precise grid
For CurrentLine = 1 To CharsDown
For CurrentColumn = 1 To CharsAcross
With CharRect
.left = GDIMappedCharWidth * (CurrentColumn - 1)
.right = GDIMappedCharWidth * CurrentColumn
.top = GDIMappedCharHeight * (CurrentLine - 1)
.bottom = GDIMappedCharHeight * CurrentLine
End With
' 2341 == DT_NOPREFIX|DT_NOCLIP|DT_VCENTER|DT_CENTER|DT_SINGLELINE
GDI.DrawText(hdc, Mid(TestString & TestString & TestString, CurrentLine+CurrentColumn, 1), 1, CharRect, 2341)
Next
Next
GDI.DeleteObject(FixedFontGDI)
G.ReleaseHdc(hdc)