没有时间翻译,各位见谅啊?代码很简单,注意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