检测打印机状态(VB实现)

来源:互联网 发布:国防生知乎 编辑:程序博客网 时间:2024/04/27 16:07

       没有时间翻译,各位见谅啊?代码很简单,注意API的使用!

Check this out... I found this while surfing internet from Spanish site

1. Start a new project in Visual Basic. Form1 is created by default.


2. Add two CommandButtons, two ListBoxes and a Timer control to Form1.


3. Paste the following code into the Form's module:


   Option Explicit


   Private Sub Command1_Click()
      'Enable the timer to begin printer status checks
      Timer1.Enabled = True


      'Enable/disable start/stop buttons
      Command1.Enabled = False
      Command2.Enabled = True
   End Sub


   Private Sub Command2_Click()
      'Clear the lists
      List1.Clear
      List2.Clear


      'Disable timer to stop further printer checks
      Timer1.Enabled = False


      'Enable/disable start/stop buttons
      Command1.Enabled = True
      Command2.Enabled = False
   End Sub


   Private Sub Form_Load()
      'Initialize captions for control buttons
      Command1.Caption = "Start"
      Command2.Caption = "Stop"


      'Disable stop button
      Command2.Enabled = False


      'Set interval for printer status checking to 1/2 second
      Timer1.Enabled = False
      Timer1.Interval = 500
   End Sub


   Private Sub Timer1_Timer()
      'Call sub to perform check
      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


      'Clear the lists for new info/status
      List1.Clear
      List2.Clear


      'NOTE: You can pick a printer from the Printers Collection
      'or use the EnumPrinters() API to select a printer name.


      'Use the default printer of Printers collection
      PrinterName = Printer.DeviceName


      'Set desired access security setting
      pDefaults.DesiredAccess = PRINTER_ACCESS_USE


      'Call API to get a handle to the printer
      result = OpenPrinter(PrinterName, hPrinter, pDefaults)
      If result = 0 Then
         'If an error occured, display an error and exit sub
         MsgBox "Cannot open printer " & PrinterName & ", Error: " _
           & Err.LastDllError
         Exit Sub
      End If


      'Init BytesNeeded
      BytesNeeded = 0


      'Clear the error object of any errors
      Err.Clear


      'Determine the buffer size needed to get printer info
      result = GetPrinter(hPrinter, 2, 0&, 0&, BytesNeeded)


      'Check for error calling GetPrinter
      If Err.LastDllError <> ERROR_INSUFFICIENT_BUFFER Then
         'Display an error message, close printer, and exit sub
         List1.AddItem " > GetPrinter Failed on initial call! <"
         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


      'Call GetPrinter to get the status
      result = GetPrinter(hPrinter, 2, PrinterInfo(1), ByteBuf, _
        BytesNeeded * 3)


      'Check for errors
      If result = 0 Then
         'Determine the error that occured
         LastError = Err.LastDllError()


         'Display error message, close printer, and exit sub
         List1.AddItem "Couldn't get Printer Status!"
         List1.AddItem "... Error = " & LastError
         ClosePrinter hPrinter
         Exit Sub
      End If


      'Copy contents of printer status byte array into a
      'PRINTER_INFO_2 structure to separate the individual elements
      CopyMemory PI2, PrinterInfo(1), Len(PI2)


      'Check if printer is in ready state
      If PI2.Status = 0 Then
         List1.AddItem "Printer Status = Ready"
      Else
         List1.AddItem "Printer Status = " & PI2.Status
      End If


      'Add printer name, driver, and port to list
      List1.AddItem "Printer Name = " & GetString(PI2.pPrinterName)
      List1.AddItem "Printer Driver Name = " & GetString(PI2.pDriverName)
      List1.AddItem "Printer Port Name = " & GetString(PI2.pPortName)


      'Call API to get size of buffer needed
      result = EnumJobs(hPrinter, 0&, 1, 2, 0&, 0&, BytesNeeded, NumJI2)


      'Check if there are no current jobs and display appropriate message
      If BytesNeeded = 0 Then
         List2.AddItem "No Print Jobs!"
      Else
         'Redim byte array to hold info about print job
         ReDim JobInfo(1 To BytesNeeded * 3)


         'Call API to get print job info
         result = EnumJobs(hPrinter, 0&, 1, 2, JobInfo(1), _
           BytesNeeded * 3, ByteBuf, NumJI2)


         'Check for errors
         If result = 0 Then
            'Get and display error, close printer, and exit sub
            LastError = Err.LastDllError
            List2.AddItem " > EnumJobs Failed on second call! <"
            List2.AddItem "... Error = " & LastError
            ClosePrinter hPrinter
            Exit Sub
         End If


         'Copy contents of print job info byte array into a
         'JOB_INFO_2 structure 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


         'Display basic job status info
         List2.AddItem "Job ID = " & JI2.JobId
         List2.AddItem "Total Pages = " & JI2.TotalPages


         'Check for a ready state
         If JI2.Status = 0 Then
            tempStr = tempStr & "Ready!  "
         Else  'Check for the various print job states
            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 & "Off line  "
            End If


            If (JI2.Status And JOB_STATUS_PAUSED) > 0 Then
               tempStr = tempStr & "Paused  "
            End If


            If (JI2.Status And JOB_STATUS_ERROR) > 0 Then
               tempStr = tempStr & "Error  "
            End If


            If (JI2.Status And JOB_STATUS_PAPEROUT) > 0 Then
               tempStr = tempStr & "Paper Out  "
            End If


            If (JI2.Status And JOB_STATUS_PRINTING) > 0 Then
               tempStr = tempStr & "Printing  "
            End If


            If (JI2.Status And JOB_STATUS_USER_INTERVENTION) > 0 Then
               tempStr = tempStr & "User Intervention Needed  "
            End If


            If Len(tempStr) = 0 Then
               tempStr = "Unknown Status of " & JI2.Status
            End If
         End If


         'Display the status
         List2.AddItem tempStr
         Debug.Print tempStr
      End If


      'Close the printer handle
      ClosePrinter hPrinter
   End Sub


4. From the Project menu add a new Module and paste in the following code:


   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


      'Check for zero address
      If PtrStr = 0 Then
         GetString = " "
         Exit Function
      End If


      'Copy data from PtrStr to buffer
      CopyMemory ByVal StrBuff, ByVal PtrStr, 64


      'Strp any trailing nulls from sting
      GetString = StripNulls(StrBuff)
   End Function


   Public Function StripNulls(OriginalStr As String) As String
      'Strip any trailing nulls from input string
      If (InStr(OriginalStr, Chr(0)) > 0) Then
         OriginalStr = Left(OriginalStr, InStr(OriginalStr, Chr(0)) - 1)
      End If


      'Return modified string
      StripNulls = OriginalStr
   End Function

thanks
bhaspup
 
Comment from charlotte_keane
Date: 12/21/2005 11:19PM PST
 Author Comment 


DeadlyTrev

how do i put this code in vb

HKEY_CURRENT_CONFIG/System/CurrentControlSet/Control/Print/Printers/<printer_name>
      PrinterOnline DWORD


bhaspup

i tried your code but it does not get the correct status
 
Comment from DeadlyTrev
Date: 12/22/2005 04:08PM PST
 Comment 


'You need some registry reading/writing routines;
'The code below handles all the everyday aspects of registry I/O for VB6
'You just need the QueryValue Function
'
'    Dim rtn as long
'    Dim pstatus as  long
'    rtn = QueryValue(HKEY_CURRENT_CONFIG, "System/CurrentControlSet/Control/Print/Printers/<printer_name>", "PrinterOnline", pstatus)

Public Const REG_SZ = 1
Public Const REG_DWORD = 4
Public Const HKEY_CURRENT_USER = &H80000001
Public Const HKEY_LOCAL_MACHINE = &H80000002
Public Const HKEY_CURRENT_CONFIG = &H80000005
Public Const KEY_ALL_ACCESS = &H3F
Public Const ERROR_NONE = 0
Public Const REG_OPTION_NON_VOLATILE = 0

Private Declare Function RegOpenKeyEx Lib "advapi32" Alias "RegOpenKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long, phkResult As Long) As Long
Private Declare Function RegCloseKey Lib "advapi32" (ByVal hKey As Long) As Long
Private Declare Function RegQueryValueExLong Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, lpData As Long, lpcbData As Long) As Long
Private Declare Function RegQueryValueExNULL Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As Long, lpcbData As Long) As Long
Private Declare Function RegQueryValueExString Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long, ByVal lpData As String, lpcbData As Long) As Long
Private Declare Function RegSetValueExString Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, ByVal lpValue As String, ByVal cbData As Long) As Long
Private Declare Function RegSetValueExLong Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long, lpValue As Long, ByVal cbData As Long) As Long
Private Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal hKey As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal dwOptions As Long, ByVal samDesired As Long, ByVal lpSecurityAttributes As Long, phkResult As Long, lpdwDisposition As Long) As Long

Public Function QueryValue(hKey As Long, sKeyName As String, sValueName As String, vValue As Variant) As Long

    Dim lRetVal As Long         'result of the API functions
         
    lRetVal = RegOpenKeyEx(hKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    If (lRetVal <> 0) Then GoTo leave
    lRetVal = QueryValueEx(hKey, sValueName, vValue)
    If (lRetVal <> 0) Then GoTo leave
    RegCloseKey (hKey)
leave:
    QueryValue = lRetVal

End Function

Public Function QueryValueEx(ByVal lhKey As Long, ByVal szValueName As String, vValue As Variant) As Long
   
    Dim cch As Long
    Dim lrc As Long
    Dim lType As Long
    Dim lValue As Long
    Dim sValue As String

    On Error GoTo QueryValueExError

    ' Determine the size and type of data to be read
    lrc = RegQueryValueExNULL(lhKey, szValueName, 0&, lType, 0&, cch)
    If lrc <> ERROR_NONE Then Error 5
    Select Case lType
        ' For strings
        Case REG_SZ:
            sValue = String$(cch, 0)
            lrc = RegQueryValueExString(lhKey, szValueName, 0&, lType, sValue, cch)
            If lrc = ERROR_NONE Then
                vValue = Left$(sValue, cch - 1)
            Else
                vValue = vbNullString
            End If
        ' For DWORDS
        Case REG_DWORD:
            lrc = RegQueryValueExLong(lhKey, szValueName, 0&, lType, lValue, cch)
            If lrc = ERROR_NONE Then vValue = lValue
        Case Else
            'all other data types not supported
            lrc = -1
            vValue = Empty
    End Select

QueryValueExExit:
    QueryValueEx = lrc
    Exit Function

QueryValueExError:
    Resume QueryValueExExit

End Function

Public Function SetKeyValue(hKey As Long, sKeyName As String, sValueName As String, vValueSetting As Variant, lValueType As Long) As Long
   
    Dim lRetVal As Long      'result of the SetValueEx function
    Dim tmpkey As Long
   
    tmpkey = hKey
    'open the specified key
    lRetVal = RegOpenKeyEx(hKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    If lRetVal = 2 Then
          lRetVal = CreateNewKey(sKeyName, tmpkey)
          hKey = tmpkey
          lRetVal = RegOpenKeyEx(hKey, sKeyName, 0, KEY_ALL_ACCESS, hKey)
    End If
    If (lRetVal <> 0) Then GoTo leave
    lRetVal = SetValueEx(hKey, sValueName, lValueType, vValueSetting)
    If (lRetVal <> 0) Then GoTo leave
    RegCloseKey (hKey)
leave:
    SetKeyValue = lRetVal

End Function

Private Function CreateNewKey(sNewKeyName As String, lPredefinedKey As Long) As Long

    Dim hNewKey As Long         'handle to the new key
    Dim lRetVal As Long         'result of the RegCreateKeyEx function

    lRetVal = RegCreateKeyEx(lPredefinedKey, sNewKeyName, 0&, vbNullString, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0&, hNewKey, lRetVal)
    If lRetVal = 0 Then RegCloseKey (hNewKey)
    CreateNewKey = lRetVal

End Function

Private Function SetValueEx(ByVal hKey As Long, sValueName As String, lType As Long, vValue As Variant) As Long
   
    Dim lValue As Long
    Dim sValue As String
   
    Select Case lType
        Case REG_SZ
            sValue = vValue & Chr$(0)
            SetValueEx = RegSetValueExString(hKey, sValueName, 0&, lType, sValue, Len(sValue))
        Case REG_DWORD
            lValue = vValue
            SetValueEx = RegSetValueExLong(hKey, sValueName, 0&, lType, lValue, 4)
        End Select

End Function

 
Comment from charlotte_keane
Date: 12/23/2005 12:57AM PST
 Author Comment