|
|
Every user is allowed to get the printer status but only users
with sufficient access rights may change the printer settings.
To request this level of access to a printer
you must set the DesiredAccess
member of the PRINTER_DEFAULTS structure passed to the OpenPrinter call.
Private Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As Long
DesiredAccess As Long
End Type
Private Declare Function OpenPrinter Lib "winspool.drv" _
Alias "OpenPrinterA" (ByVal pPrinterName As String, _
phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long
Public Enum PrinterAccessRights
PRINTER_ACCESS_ADMINISTER = &H4
PRINTER_ACCESS_USE = &H8
PRINTER_ALL_ACCESS = &HF000C
End
Enum
You pass the Printer.DeviceName to OpenPrinter this to get the handle.
Dim lret As Long
Dim pDef As PRINTER_DEFAULTS
pdef.DesiredAccess = PRINTER_ALL_ACCESS
lret = OpenPrinter(Printer.DeviceName, mhPrinter,
pDef)
If the user has sufficient priveledge to administer
the printer then the handle mhPrinter will be
set and can be used in subsequent calls to GetPrinter and SetPrinter
You should
check that no error has occured by checking that Err.LastDllError is zero.
The printer can be paused and resumed and the jobs may be purged from it using the printer control commands.
Public Enum Printer_Control_Commands
PRINTER_CONTROL_PAUSE = 1
PRINTER_CONTROL_RESUME = 2
PRINTER_CONTROL_PURGE = 3
PRINTER_CONTROL_SET_STATUS = 4
End
Enum
These commands are sent to the printer using the SetPrinter api call.
Private Declare Function SetPrinterApi Lib "winspool.drv" Alias _ Thus the code to control the printer would look like:
Public Sub PrinterCommand (ByVal DeviceName
As String, ByVal cmd As
Printer_Control_Commands ) In the above code passing Printer_Control_Set_Status in the cmd
parameter has no effect. This is because to set the status of the
current job you need to pass the new status in the pPrinter parameter of the SetPrinter call: Public Sub SetPrinterStatus(ByVal DeviceName
As String, ByVal newStatus
As Printer_Status) As seen in
this article there a number of
additional properties that you can get related to the printer - such as
its location, comment etc. In this example we change the comment for the
printer: Dim lret As Long The result from this is an array of Long data types, part of which corresponds to a PRINTER_INFO_2 data structure. From this structure we can deduce
that the comment is held in the memory address pointed to by buffer(5). To change the comment we just set this buffer
to the address of a string that contains the new comment.
You can get the memory address (pointer) for any Visual basic string using the undocumented
StrPtr function:
lpString = StrPtr(sVar)
However, since we are using the ANSI version of the Api call, and Visual Basic
4 or above always stores strings as unicode internally, we must convert the string to ANSI before getting the
resultant string's address. To do this we use the StrConv function:
sVar = StrConv(sVar, vbFromUnicode)
Thus the resulting code is:
Dim lpString As Long If you have any feedback on this article, or any
other on this site, you can contact us with this form
"SetPrinterA" (ByVal hPrinter As Long, _
ByVal Level As Long, _
buffer As Long, _
ByVal Command As Long) As Long
Dim
lRet As Long
Dim
mhPrinter As Long
Dim
pDef As Printer_Defaults
'\\ Open the printer in admin. mode
pdef.DesiredAccess = PRINTER_ALL_ACCESS
lret = OpenPrinter(DeviceName, mhPrinter, pDef)
'\\ Send the command
' (both
Level and Buffer are empty to send commands)
lRet = SetPrinterApi(mhPrinter, 0, 0,cmd)
'\\ Close
the printer
lRet =
ClosePrinter(mhPrinter)
End
Sub Setting the status of the current job
Dim lRet As Long
Dim mhPrinter As Long
Dim
pDef As Printer_Defaults
'\\ Open the printer in admin. mode
pdef.DesiredAccess = PRINTER_ALL_ACCESS
lret = OpenPrinter(DeviceName, mhPrinter, pDef)
'\\ Set the new status
lRet = SetPrinterApi(mhPrinter, newStatus,
0,PRINTER_CONTROL_SET_STATUS)
'\\ Close the printer
lRet = ClosePrinter(mhPrinter)
End Sub Changing other properties of the selected printer
However, if the
value of the buffer is not zero then you need to get the buffer from the
printer, modify the bits you want to change and then pass that buffer back
to the printer driver. If you change the size of the buffer
then you will cause a GPF.
Dim SizeNeeded As Long
Dim buffer() As Long
ReDim Preserve buffer(0 To 1) As Long
lret = GetPrinterApi(mhPrinter, 2,
buffer(0), UBound(buffer), SizeNeeded)
ReDim Preserve buffer(0 To (SizeNeeded / 4) +
3) As Long
lret = GetPrinterApi(mhPrinter, 2,
buffer(0), UBound(buffer) * 4, SizeNeeded) Getting a pointer to a string
Dim sVar As String
sVar = "New printer comment"
sVar = StrConv(sVar, vbFromUnicode)
lpString = StrPtr(sVar)
buffer(5) = lpString
'\\ Save the new setting to the printer
lRet = SetPrinter(mhPrinter,2,buffer(0),0)