VerySource

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 630|回复: 1

自定义纸张大小时ResetDC无效,但返回成功

[复制链接]

1

主题

4

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
发表于 2020-3-5 22:30:02 | 显示全部楼层 |阅读模式

'打印纸相关属性
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的打印首选项,发现默认打印纸根本没有改变。
回复

使用道具 举报

1

主题

4

帖子

4.00

积分

新手上路

Rank: 1

积分
4.00
 楼主| 发表于 2020-5-20 20:15:01 | 显示全部楼层
刚发现一个问题,就是调用了UsePaper后,如果再设置打印纸方向,就会恢复默认纸张大小
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|CopyRight © 2008-2023|verysource.com ( 京ICP备17048824号-1 )

快速回复 返回顶部 返回列表