在VisualBasic中检测打印机状态的代码(本站翻译)

这是一段利用API函数来取得打印信息的程序

'1、开始一个新的vb项目,系统将自动创建Form1窗体
'2、在Form1上添加两个按钮,两个列表框Listbox和一个Timer定时器
'3、粘贴下面的代码到Form1窗体的的代码区域?

Option Explicit
Private Sub Command1_Click()
    '启用定时器开始检测打印状态
    Timer1.Enabled = True
    '允许/禁止 开始/停止 按钮
    Command1.Enabled = False
    Command2.Enabled = True
End Sub

Private Sub Command2_Click()
    '清除列表
    List1.Clear
    List2.Clear
    '禁用定时器,停止检测打印机状态
    Timer1.Enabled = False
    '允许/禁止 开始/停止 按钮
    Command1.Enabled = True
    Command2.Enabled = False
End Sub

Private Sub Form_Load()
    '初始按钮文本
    Command1.Caption = "Start"
    Command2.Caption = "Stop"
    '禁用停止按钮
    Command2.Enabled = False
    '设置打印机状态检测间隔,即interval为1/2秒
    Timer1.Enabled = False
    Timer1.Interval = 500
End Sub


Private Sub Timer1_Timer()
    '调用CheckPrinter检测打印机状态
    CheckPrinter
End Sub

Private Sub CheckPrinter()
    Dim hPrinter As Long
    Dim ByteBuf As Long, BytesNeeded As Long
    Dim PI2 As PRINTER_INFO_2
    Dim JI2 As JOB_INFO_2
    Dim PrinterInfo() As Byte
    Dim JobInfo() As Byte
    Dim result As Long, LastError As Long
    Dim PrinterName As String, tempStr As String
    Dim NumJI2 As Long
    Dim pDefaults As PRINTER_DEFAULTS
   
    '有新信息或状态时清空列表
    List1.Clear
    List2.Clear
   
    '注意:你能通过打印机集合来选择一个打印机
    '或者通过EnumPrinters() API函数来选择一个打印机名称
   
    '使用打印机集合中的缺省打印机
    PrinterName = Printer.DeviceName
   
    'Set desired access security setting
    pDefaults.DesiredAccess = PRINTER_ACCESS_USE
   
    '调用API函数得到打印机句柄
    result = OpenPrinter(PrinterName, hPrinter, pDefaults)
    If result = 0 Then
        '如果产生错误就显示并退出这个过程
        MsgBox "不能打开打印机:" & PrinterName & ", 错误: " & Err.LastDllError
        Exit Sub
    End If
   
    '初始化 BytesNeeded
    BytesNeeded = 0
   
    '清除错误信息
    Err.Clear
   
    '确定打印机信息所需要的缓冲区大小
    result = GetPrinter(hPrinter, 2, 0&, 0&, BytesNeeded)
   
    '检测调用GetPrinter所产生的错误
    If Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER Then
        '显示错误消息,关闭打印机并退出子过程
        List1.AddItem " > 第一次调用GetPrinter产生错误! <"
        ClosePrinter hPrinter
        Exit Sub
    End If

    'Due to a problem with GetPrinter, we must allocate a buffer as
    'much as 3 times larger than the value returned by the initial
    'call to GetPrinter.  See page 790 of Charles Petzold's book
    '"Programming Windows 95" for additional information
    ReDim PrinterInfo(1 To BytesNeeded * 3)
   
    ByteBuf = BytesNeeded
   
    '检测打印机状态
    result = GetPrinter(hPrinter, 2, PrinterInfo(1), ByteBuf, BytesNeeded * 3)
   
    '检测错误
    If result = 0 Then
        '确定错误的内容
        LastError = Err.LastDllError()
          '显示消息,关闭打印机,退出子过程
        List1.AddItem "不能得到打印机状态!"
        List1.AddItem "... 错误 = " & LastError
        ClosePrinter hPrinter
        Exit Sub
    End If
   
    '拷贝打印机状态到PRINTER_INFO_2 结构
    CopyMemory PI2, PrinterInfo(1), Len(PI2)
   
    '检测打印机是否准备好了
    If PI2.Status = 0 Then
        List1.AddItem "打印机状态= 准备好了"
    Else
        List1.AddItem "打印机状态= " & PI2.Status
    End If
   
    '添加打印机名称,驱动和端口列表
    List1.AddItem "打印机名称= " & GetString(PI2.pPrinterName)
    List1.AddItem "打印机驱动名称= " & GetString(PI2.pDriverName)
    List1.AddItem "打印机端口名称= " & GetString(PI2.pPortName)
   
    '通过API得到缓冲区尺寸
    result = EnumJobs(hPrinter, 0&, 1, 2, 0&, 0&, BytesNeeded, NumJI2)
   
    '检测是否存在打印任务,并显示适当的信息
    If BytesNeeded = 0 Then
        List2.AddItem "没有打印任务!"
    Else
        '重定义数组用来锁定打印任务信息
        ReDim JobInfo(1 To BytesNeeded * 3)
        '调用API得到打印任务信息
        result = EnumJobs(hPrinter, 0&, 1, 2, JobInfo(1), BytesNeeded * 3, ByteBuf, NumJI2)
       
        '检测错误
        If result = 0 Then
            '得到并显示错误,关闭打印机然后退出子过程
            LastError = Err.LastDllError
            List2.AddItem " > 第二次枚举打印任务失败! <"
            List2.AddItem "... 错误 = " & LastError
            ClosePrinter hPrinter
            Exit Sub
        End If
   
        '拷贝打印任务信息到JOB_INFO_2 to separate the individual elements
        CopyMemory JI2, JobInfo(1), Len(JI2)
        Debug.Print "Job ID" & vbTab & JI2.JobId
        Debug.Print "Name Of Printer" & vbTab & GetString(JI2.pPrinterName)
        Debug.Print "Name Of Machine That Created Job" & vbTab & GetString(JI2.pMachineName)
        Debug.Print "Print Job Owner's Name" & vbTab & GetString(JI2.pUserName)
        Debug.Print "Name Of Document" & vbTab & GetString(JI2.pDocument)
        Debug.Print "Name Of User To Notify" & vbTab & GetString(JI2.pNotifyName)
        Debug.Print "Type Of Data" & vbTab & GetString(JI2.pDatatype)
        Debug.Print "Print Processor" & vbTab & GetString(JI2.pPrintProcessor)
        Debug.Print "Print Processor Parameters" & vbTab & GetString(JI2.pParameters)
        Debug.Print "Print Driver Name" & vbTab & GetString(JI2.pDriverName)
        Debug.Print "Print Job 'P' Status" & vbTab & GetString(JI2.pStatus)
        Debug.Print "Print Job Status" & vbTab & JI2.Status
        Debug.Print "Print Job Priority" & vbTab & JI2.Priority
        Debug.Print "Position in Queue" & vbTab & JI2.Position
        Debug.Print "Earliest Time Job Can Be Printed" & vbTab & JI2.StartTime
        Debug.Print "Latest Time Job Will Be Printed" & vbTab & JI2.UntilTime
        Debug.Print "Total Pages For Entire Job" & vbTab & JI2.TotalPages
        Debug.Print "Size of Job In Bytes" & vbTab & JI2.Size
        'Due to a bug since NT 3.51, the time member is not set correctly
        'so don't use it.
        Debug.Print "Elapsed Print Time" & vbTab & JI2.time
        Debug.Print "Pages Printed So Far" & vbTab & JI2.PagesPrinted
   
        '显示基础工作状态信息
        List2.AddItem "任务ID = " & JI2.JobId
        List2.AddItem "页数= " & JI2.TotalPages
       
        '检测ready状态
        If JI2.Status = 0 Then
            tempStr = tempStr & "准备  "
        Else  '检测打印机状态
            If (JI2.Status And JOB_STATUS_SPOOLING) > 0 Then
                tempStr = tempStr & "Spooling  "
            End If
           
            If (JI2.Status And JOB_STATUS_OFFLINE) > 0 Then
                tempStr = tempStr & "离线"
            End If
           
            If (JI2.Status And JOB_STATUS_PAUSED) > 0 Then
                tempStr = tempStr & "暂停"
            End If
           
            If (JI2.Status And JOB_STATUS_ERROR) > 0 Then
                tempStr = tempStr & "错误"
            End If
           
            If (JI2.Status And JOB_STATUS_PAPEROUT) > 0 Then
                tempStr = tempStr & "出纸"
            End If
           
            If (JI2.Status And JOB_STATUS_PRINTING) > 0 Then
                tempStr = tempStr & "打印"
            End If
           
            If (JI2.Status And JOB_STATUS_USER_INTERVENTION) > 0 Then
                tempStr = tempStr & "用户干预"
            End If
           
            If Len(tempStr) = 0 Then
                tempStr = "位置状态:" & JI2.Status
            End If
        End If
        '显示状态
        List2.AddItem tempStr
        Debug.Print tempStr
    End If
       
    '关闭打印机句柄
    ClosePrinter hPrinter
End Sub
 

'4. 从工程菜单添加一个新的Module并且粘贴下面的代码
Option Explicit

Public Declare Function OpenPrinter Lib "winspool.drv" Alias "OpenPrinterA" (ByVal pPrinterName As String, phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long
Public Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Byte, ByVal cbBuf As Long, pcbNeeded As Long) As Long
Public Declare Function ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Declare Function EnumJobs Lib "winspool.drv" Alias "EnumJobsA" (ByVal hPrinter As Long, ByVal FirstJob As Long, ByVal NoJobs As Long, ByVal Level As Long, pJob As Byte, ByVal cdBuf As Long, pcbNeeded As Long, pcReturned As Long) As Long

'constants for PRINTER_DEFAULTS structure
Public Const PRINTER_ACCESS_USE = &H8
Public Const PRINTER_ACCESS_ADMINISTER = &H4

'constants for DEVMODE structure
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32

Public Type PRINTER_DEFAULTS
    pDatatype As String
    pDevMode As Long
    DesiredAccess As Long
End Type

Public Type DEVMODE
    dmDeviceName As String * CCHDEVICENAME
    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 * CCHFORMNAME
    dmLogPixels As Integer
    dmBitsPerPel As Long
    dmPelsWidth As Long
    dmPelsHeight As Long
    dmDisplayFlags As Long
    dmDisplayFrequency As Long
End Type

Type SYSTEMTIME
    wYear As Integer
    wMonth As Integer
    wDayOfWeek As Integer
    wDay As Integer
    wHour As Integer
    wMinute As Integer
    wSecond As Integer
    wMilliseconds As Integer
End Type

Type JOB_INFO_2
    JobId As Long
    pPrinterName As Long
    pMachineName As Long
    pUserName As Long
    pDocument As Long
    pNotifyName As Long
    pDatatype As Long
    pPrintProcessor As Long
    pParameters As Long
    pDriverName As Long
    pDevMode As Long
    pStatus As Long
    pSecurityDescriptor As Long
    Status As Long
    Priority As Long
    Position As Long
    StartTime As Long
    UntilTime As Long
    TotalPages As Long
    Size As Long
    Submitted As SYSTEMTIME
    time As Long
    PagesPrinted As Long
End Type

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 Long
End Type

Public Const ERROR_INSUFFICIENT_BUFFER = 122
Public Const PRINTER_STATUS_BUSY = &H200
Public Const PRINTER_STATUS_DOOR_OPEN = &H400000
Public Const PRINTER_STATUS_ERROR = &H2
Public Const PRINTER_STATUS_INITIALIZING = &H8000
Public Const PRINTER_STATUS_IO_ACTIVE = &H100
Public Const PRINTER_STATUS_MANUAL_FEED = &H20
Public Const PRINTER_STATUS_NO_TONER = &H40000
Public Const PRINTER_STATUS_NOT_AVAILABLE = &H1000
Public Const PRINTER_STATUS_OFFLINE = &H80
Public Const PRINTER_STATUS_OUT_OF_MEMORY = &H200000
Public Const PRINTER_STATUS_OUTPUT_BIN_FULL = &H800
Public Const PRINTER_STATUS_PAGE_PUNT = &H80000
Public Const PRINTER_STATUS_PAPER_JAM = &H8
Public Const PRINTER_STATUS_PAPER_OUT = &H10
Public Const PRINTER_STATUS_PAPER_PROBLEM = &H40
Public Const PRINTER_STATUS_PAUSED = &H1
Public Const PRINTER_STATUS_PENDING_DELETION = &H4
Public Const PRINTER_STATUS_PRINTING = &H400
Public Const PRINTER_STATUS_PROCESSING = &H4000
Public Const PRINTER_STATUS_TONER_LOW = &H20000
Public Const PRINTER_STATUS_USER_INTERVENTION = &H100000
Public Const PRINTER_STATUS_WAITING = &H2000
Public Const PRINTER_STATUS_WARMING_UP = &H10000
Public Const JOB_STATUS_PAUSED = &H1
Public Const JOB_STATUS_ERROR = &H2
Public Const JOB_STATUS_DELETING = &H4
Public Const JOB_STATUS_SPOOLING = &H8
Public Const JOB_STATUS_PRINTING = &H10
Public Const JOB_STATUS_OFFLINE = &H20
Public Const JOB_STATUS_PAPEROUT = &H40
Public Const JOB_STATUS_PRINTED = &H80
Public Const JOB_STATUS_DELETED = &H100
Public Const JOB_STATUS_BLOCKED_DEVQ = &H200
Public Const JOB_STATUS_USER_INTERVENTION = &H400
Public Const JOB_STATUS_RESTART = &H800

Public Function GetString(ByVal PtrStr As Long) As String
    Dim StrBuff As String * 256
    '检测参数是否为0
    If PtrStr = 0 Then
        GetString = " "
        Exit Function
    End If
   
    '从PtrStr拷贝数据到缓冲区
    CopyMemory ByVal StrBuff, ByVal PtrStr, 64
   
    '去除字符串中的NULLS值
    GetString = StripNulls(StrBuff)
End Function

Public Function StripNulls(OriginalStr As String) As String
    '去除字符串中的NULLS值
    If (InStr(OriginalStr, Chr(0)) > 0) Then
        OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
    End If
   
    '回传修改后的字符串
    StripNulls = OriginalStr
End Function
 

Tags:visual basic  打印  状态  代码  

0 Comment so far



Leave a reply