首先向奋战在抗“非典”一线的所有战士敬礼!
这个问题在51放假前一困扰我有几天了,现在还是没解决。我通过关键字搜索了所有的相关问题,浏览了最近的讨论,基本上提到的方法我都用过了,还是不行。
我现在的程序可以向默认打印机添加自定义大小纸张,但就是没有办法将他设为默认格式纸张。2000系统下控制面板中的打印机设置也可以手动添加自定义打印纸,可是修改默认格式打印纸的地方却没有出现添加的自定义大小的打印纸,这与打印机供应商提供的打印驱动程序有关吗,如果有如何解决?
非常欢迎大家提供有意义的帮助,分数不够我会再加。
以下是我目前程序的主要片断:
'************ 添加自定义大小纸张(能起作用)
Private Sub Command1_Click()
    Dim pDevMode As DEVMODE
    Dim aDevMode() As Byte  ' Working DEVMODE
    Dim hPrtDC As Long          ' Handle to Printer DC
    Dim nSize As Long           ' Size of DEVMODE
    Dim FormName As String
    Dim PrinterName As String
    Dim PrinterHandler As Long
    Dim FormSize As SIZEL
    
    PrinterName = Printer.DeviceName
    
    '* Use special, user-defined form.
    FormName = txtPaperForm.Text
    FormSize.cx = CLng(txtWidth.Text) * 1000
    FormSize.cy = CLng(txtHeight.Text) * 1000
    OpenPrinter PrinterName, PrinterHandler, 0&
    AddNewForm PrinterHandler, FormSize, FormName '*定义见下
    
    cbxPaperForms.Clear
    Call GetPaperForms
    cbxPaperForms.ListIndex = cbxPaperForms.ListCount - 1'UseForm FormName
End SubPublic Function AddNewForm(PrinterHandle As Long, FormSize As SIZEL, _
                           FormName As String) As String
Dim FI1 As sFORM_INFO_1
Dim aFI1() As Byte
Dim RetVal As LongWith FI1
    .Flags = 0
    .pName = FormName
    With .Size
        .cx = FormSize.cx
        .cy = FormSize.cy
    End With
    With .ImageableArea
        .Left = 0
        .Top = 0
        .Right = FI1.Size.cx
        .Bottom = FI1.Size.cy
    End With
End With
ReDim aFI1(Len(FI1))
Call CopyMemory(aFI1(0), FI1, Len(FI1))
RetVal = AddForm(PrinterHandle, 1, aFI1(0))
If RetVal = 0 Then
    If Err.LastDllError = 5 Then
        MsgBox "你没有向 " & _
           Printer.DeviceName & " 添加自定义的打印纸格式的权限!", vbExclamation, "权限禁止!"
    Else
        MsgBox "Error: " & Err.LastDllError, "Error Adding Form"
    End If
    AddNewForm = "none"
Else
    AddNewForm = FI1.pName
End If
End Function'*********************选择添加的自定义大小纸张(不起作用)
Private Sub Command2_Click()
    Dim FormName As String
    Dim PaperDesc As String
    Dim tempIndex As Integer
    
    If cbxPaperForms.ListIndex = -1 Then
        MsgBox "请先选择你想要的打印纸格式", vbInformation, "提示"
        cbxPaperForms.SetFocus
        Exit Sub
    End If
    
    PaperDesc = cbxPaperForms.Text
    FormName = Left(PaperDesc, InStr(1, PaperDesc, "--") - 1)
    If MsgBox("确定选择 " & FormName & " 格式的打印纸?", vbYesNoCancel, "确认") = vbYes Then
        Call SelectForm(FormName, Me.hwnd) '*定义见下
        tempIndex = cbxPaperForms.ListIndex
        cbxPaperForms.ListIndex = Printer.PaperSize - 1
        txtCurrPaperForm.Text = cbxPaperForms.Text
        cbxPaperForms.ListIndex = tempIndex
'        Printer.PaperSize = cbxPaperForms.ListIndex + 1
'        txtCurrPaperForm.Text = cbxPaperForms.Text
    End If
    'Printer.PaperSize = 123 'bxPaperForms.ListIndex
End SubPublic Sub SelectForm(FormName As String, ByVal MyhWnd As Long)
    Dim nSize As Long           ' Size of DEVMODE
    Dim pDevMode As DEVMODE
    Dim PrinterHandle As Long   ' Handle to printer
    Dim hPrtDC As Long          ' Handle to Printer DC
    Dim PrinterName As String
    Dim aDevMode() As Byte      ' Working DEVMODE
    Dim FormSize As SIZEL
    
    PrinterName = Printer.DeviceName  ' Current printer
    hPrtDC = Printer.hdc              ' hDC for current Printer
    
    ' Get a handle to the printer.
    If OpenPrinter(PrinterName, PrinterHandle, 0&) Then
        ' Retrieve the size of the DEVMODE.
        nSize = DocumentProperties(MyhWnd, PrinterHandle, PrinterName, 0&, _
                0&, 0&)
        ' Reserve memory for the actual size of the DEVMODE.
        ReDim aDevMode(1 To nSize)
    
        ' Fill the DEVMODE from the printer.
        nSize = DocumentProperties(MyhWnd, PrinterHandle, PrinterName, _
                aDevMode(1), 0&, DM_OUT_BUFFER)
        ' Copy the Public (predefined) portion of the DEVMODE.
        Call CopyMemory(pDevMode, aDevMode(1), Len(pDevMode))
        
        ' Change the appropriate member in the DevMode.
        ' In this case, you want to change the form name.
        pDevMode.dmFormName = FormName & Chr(0)  ' Must be NULL terminated!
        ' Set the dmFields bit flag to indicate what you are changing.
        pDevMode.dmFields = DM_FORMNAME
    
        ' Copy your changes back, then update DEVMODE.
        Call CopyMemory(aDevMode(1), pDevMode, Len(pDevMode))
        nSize = DocumentProperties(MyhWnd, PrinterHandle, PrinterName, _
                aDevMode(1), aDevMode(1), DM_IN_BUFFER Or DM_OUT_BUFFER)
    
        nSize = ResetDC(hPrtDC, aDevMode(1))   ' Reset the DEVMODE for the DC.
    
        ' Close the handle when you are finished with it.
        ClosePrinter (PrinterHandle)
    End If
End Sub

解决方案 »

  1.   

    借花献佛,以下代码搞定;Public Enum PrinterOrientationConstants        OrientPortrait = 1        OrientLandscape = 2End EnumPrivate Type DEVMODE        dmDeviceName As String * 32        dmSpecVersion As Integer        dmDriverVersion As Integer        dmSize As Integer        dmDriverExtra As Integer        dmFields As Long        dmOrientation As Integer        dmPaperSize As Integer        dmPaperLength As Integer        dmPaperWidth As Integer        dmScale As Integer        dmCopies As Integer        dmDefaultSource As Integer        dmPrintQuality As Integer        dmColor As Integer        dmDuplex As Integer        dmYResolution As Integer        dmTTOption As Integer        dmCollate As Integer        dmFormName As String * 32        dmUnusedPadding As Integer        dmBitsPerPel As Integer        dmPelsWidth As Long        dmPelsHeight As Long        dmDisplayFlags As Long        dmDisplayFrequency As LongEnd TypePrivate Type PRINTER_DEFAULTS        pDataType As String        pDevMode As Long        DesiredAccess As LongEnd TypePrivate Type PRINTER_INFO_2        pServerName As Long        pPrinterName As Long        pShareName As Long        pPortName As Long        pDriverName As Long        pComment As Long        pLocation As Long        pDevMode As Long        pSepFile As Long        pPrintProcessor As Long        pDataType As Long        pParameters As Long        pSecurityDescriptor As Long        Attributes As Long        Priority As Long        DefaultPriority As Long        StartTime As Long        UntilTime As Long        Status As Long        cJobs As Long        AveragePPM As LongEnd TypePrivate Const DMPAPER_A2 = 66Private Const DMPAPER_A3 = 8Private Const DMPAPER_A4 = 9Private Const DMPAPER_A5 = 11Private Const DMPAPER_B4 = 12Private Const DMPAPER_B5 = 13Private Const DM_IN_BUFFER As Long = 8Private Const DM_OUT_BUFFER As Long = 2Private Const DM_ORIENTATION As Long = &H1Private Const DM_PAPERSIZE = &H2&Private Const PRINTER_ACCESS_ADMINISTER As Long = &H4Private Const PRINTER_ACCESS_USE As Long = &H8Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)Private Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As Any) As LongPrivate Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As LongPrivate Declare Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hWnd As Long, ByVal hPrinter As Long, ByVal pDeviceName As String, pDevModeOutput As Any, pDevModeInput As Any, ByVal fMode As Long) As LongPrivate Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As LongPrivate Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal Command As Long) As LongFunction SetDefaultPrinterOrientation(ByVal eOrientation As PrinterOrientationConstants) As Boolean        Dim bDevMode() As Byte        Dim bPrinterInfo2() As Byte        Dim hPrinter As Long        Dim lResult As Long        Dim nSize As Long        Dim sPrnName As String        Dim dm As DEVMODE        Dim pd As PRINTER_DEFAULTS        Dim pi2 As PRINTER_INFO_2        ' 获取默认打印机的设备名称        sPrnName = Printer.DeviceName        ' 由于要调用SetPrinter,所以        ' 如果是在NT下就要求PRINTER_ALL_ACCESS
            
            pd.DesiredAccess = PRINTER_ALL_ACCESS   'NT        ' 获取打印机句柄        If OpenPrinter(sPrnName, hPrinter, pd) Then                ' 获取PRINTER_INFO_2结构要求的字节数               Call GetPrinter(hPrinter, 2&, 0&, 0&, nSize)                ReDim bPrinterInfo2(1 To nSize) As Byte                lResult = GetPrinter(hPrinter, 2, bPrinterInfo2(1), nSize, nSize)                Call CopyMemory(pi2, bPrinterInfo2(1), Len(pi2))                nSize = DocumentProperties(0&, hPrinter, sPrnName, 0&, 0&, 0)                      ReDim bDevMode(1 To nSize)                If pi2.pDevMode Then                        Call CopyMemory(bDevMode(1), ByVal pi2.pDevMode, Len(dm))                Else                        Call DocumentProperties(0&, hPrinter, sPrnName, bDevMode(1), 0&, DM_OUT_BUFFER)                End If                 Call CopyMemory(dm, bDevMode(1), Len(dm))                With dm                        ' 设置新的走向
                            .dmOrientation = eOrientation                        .dmFields = DM_ORIENTATION
                            
                            .dmPaperSize = DMPAPER_A4                        '.dmPaperSize = DMPAPER_A5  '将纸张大小设为A5,请自行更改所需大小                        .dmFields = DM_PAPERSIZE   '必须,否则无法设置纸张大小
                            
                    End With                Call CopyMemory(bDevMode(1), dm, Len(dm))                 Call DocumentProperties(0&, hPrinter, sPrnName, bDevMode(1), bDevMode(1), DM_IN_BUFFER Or DM_OUT_BUFFER)                 pi2.pDevMode = VarPtr(bDevMode(1))                 lResult = SetPrinter(hPrinter, 2, pi2, 0&)                 Call ClosePrinter(hPrinter)                SetDefaultPrinterOrientation = True        Else                SetDefaultPrinterOrientation = False        End IfEnd Function 
      

  2.   

    to zhou_chunlin():非常感谢你的帮助,我终于将此问题解决,先给你50分。
    不过这中间还有个问题,我不太明白,能否再帮我解答,还有50分再结,呵呵。问题是:
    在你给的代码段中
    Function SetDefaultPrinterOrientation(ByVal eOrientation As PrinterOrientationConstants) As Boolean
                .
                .
                .
                    If pi2.pDevMode Then                        Call CopyMemory(bDevMode(1), ByVal pi2.pDevMode, Len(dm))                Else                        Call DocumentProperties(0&, hPrinter, sPrnName, bDevMode(1), 0&, DM_OUT_BUFFER)                End If
                    .
                    .
                    .
    End Function
    语句If pi2.pDevMode Then是什么意思,什么作用。因我通过ApiViewer导进来的类型
    Type PRINTER_INFO_2
    中的字段pDevMode是DEVMODE型,我把他改成你上面给的long型,程序就可以正常工作了,
    这是什么道理?