|
'打印纸相关属性
Public Type PaperRegion_sq
Width As Double '打印纸宽度
Height As Double '打印纸高度
LeftMargin As Double '左边距
RightMargin As Double '右边距
TopMargin As Double '上边距
BottomMargin As Double '下边距
Left As Double
Right As Double
Top As Double
Bottom As Double
End Type
'设置夏克纸张到指定大小,单位:mm
'夏克纸张这个FormName应该存在,这里不作检查
Public Function UsePaper(pWidth As Double, pHeight As Double, Optional ByRef ErrMsg As String) As Long
'WinXP下测试
Dim aFI1() As Byte, sFI1 As sFORM_INFO_1, FormName As String
Dim PrinterName As String, hPrinter As Long
Dim nSize As Long, pDevMode As DEVMODE, aDevMode() As Byte
PrinterName = Printer.DeviceName
FormName = "夏克纸张" '测试时在控制面板-打印机和传真的文件菜单中选服务器属性,添加一个格式,叫夏克纸张,大小随意
With sFI1
.Flags = 0
.PName = FormName
.Size.cx = pWidth * 1000
.Size.cy = pHeight * 1000
.ImageableArea.Left = 0
.ImageableArea.Top = 0
.ImageableArea.Right = pWidth * 1000
.ImageableArea.Bottom = pHeight * 1000
End With
If OpenPrinter(PrinterName, hPrinter, 0&) = 0 Then GoTo ErrHandle
'修改自定义纸张
ReDim aFI1(Len(sFI1))
Call CopyMemory(aFI1(0), sFI1, Len(sFI1))
If SetForm(hPrinter, FormName, 1, aFI1(0)) = 0 Then GoTo ErrHandle
'更新Printer
nSize = DocumentProperties(0, hPrinter, PrinterName, 0&, 0&, 0&)
ReDim aDevMode(1 To nSize)
nSize = DocumentProperties(0, hPrinter, PrinterName, aDevMode(1), 0&, DM_OUT_BUFFER)
Call CopyMemory(pDevMode, aDevMode(1), Len(pDevMode))
pDevMode.dmFormName = FormName & Chr(0) ' 必须以NULL结尾!!
pDevMode.dmFields = DM_FORMNAME '设置dmFields标志位
Call CopyMemory(aDevMode(1), pDevMode, Len(pDevMode))
nSize = DocumentProperties(0, hPrinter, PrinterName, aDevMode(1), aDevMode(1), DM_IN_BUFFER Or DM_OUT_BUFFER)
nSize = ResetDC(Printer.hDC, aDevMode(1))
ClosePrinter (hPrinter) '关闭打印机
Call GetPaperRegion(vbMillimeters) '在这里观察GetPaperRegion的值出现问题,描述在后面
UsePaper = -1
Exit Function
ErrHandle:
ErrMsg = Err.LastDllError
Exit Function
End Function
'返回默认打印机首选打印纸信息
Public Function GetPaperRegion(Optional pScaleMode As ScaleModeConstants = vbPixels) As PaperRegion_sq
With GetPaperRegion
.Width = GetDeviceCaps(Printer.hDC, PHYSICALWIDTH)
.Height = GetDeviceCaps(Printer.hDC, PHYSICALHEIGHT)
.LeftMargin = GetDeviceCaps(Printer.hDC, PHYSICALOFFSETX)
.TopMargin = GetDeviceCaps(Printer.hDC, PHYSICALOFFSETY)
.RightMargin = GetDeviceCaps(Printer.hDC, PHYSICALWIDTH) - GetDeviceCaps(Printer.hDC, HORZRES) - GetDeviceCaps(Printer.hDC, PHYSICALOFFSETX)
.BottomMargin = GetDeviceCaps(Printer.hDC, PHYSICALHEIGHT) - GetDeviceCaps(Printer.hDC, VERTRES) - GetDeviceCaps(Printer.hDC, PHYSICALOFFSETY)
.Left = 0
.Top = 0
.Right = .LeftMargin + GetDeviceCaps(Printer.hDC, HORZRES)
.Bottom = .TopMargin + GetDeviceCaps(Printer.hDC, VERTRES)
End With
If pScaleMode = vbPixels Then Exit Function
Dim x As Double, y As Double
'先转换成英寸然后再转换成其它单位
x = GetDeviceCaps(Printer.hDC, LOGPIXELSX): y = GetDeviceCaps(Printer.hDC, LOGPIXELSY)
With GetPaperRegion
.Width = .Width / x
.Height = .Height / y
.LeftMargin = .LeftMargin / x
.TopMargin = .TopMargin / y
.RightMargin = .RightMargin / x
.BottomMargin = .BottomMargin / y
.Right = .Right / x
.Bottom = .Bottom / y
End With
If pScaleMode = vbInches Then Exit Function
With GetPaperRegion
.Width = Printer.ScaleX(.Width, vbInches, pScaleMode)
.Height = Printer.ScaleY(.Height, vbInches, pScaleMode)
.LeftMargin = Printer.ScaleX(.LeftMargin, vbInches, pScaleMode)
.TopMargin = Printer.ScaleY(.TopMargin, vbInches, pScaleMode)
.RightMargin = Printer.ScaleX(.RightMargin, vbInches, pScaleMode)
.BottomMargin = Printer.ScaleY(.BottomMargin, vbInches, pScaleMode)
.Right = Printer.ScaleX(.Right, vbInches, pScaleMode)
.Bottom = Printer.ScaleY(.Bottom, vbInches, pScaleMode)
End With
End Function
在UsePaper中执行了ResetDC后,通过GetPaperRegion函数来观察宽度和高度,发现对于LQ1600K可以自定义,对联想激光打印机Lj2500就不行,但返回的却是正确的DC值
退出UsePaper时,通过GetPaperRegion函数来观察宽度和高度,发现又变成默认打印纸大小了。不退出进程,观察LQ1600K的打印首选项,发现默认打印纸根本没有改变。 |
|