| {\rtf1\ansi\ansicpg1252\deff0\deflang1044{\fonttbl{\f0\fnil\fcharset0 MS Sans Serif;}} \viewkind4\uc1\pard\f0\fs17 1. Getting permission to administer the printer \par \par Every user is allowed to get the printer status but only users with sufficient access rights may change the printer settings. \par 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. \par \par <-- API Declaration --> \par Private Type PRINTER_DEFAULTS \par pDatatype As String \par pDevMode As Long \par DesiredAccess As Long \par End Type \par \par Private Declare Function OpenPrinter Lib "winspool.drv" _ \par Alias "OpenPrinterA" (ByVal pPrinterName As String, _ \par phPrinter As Long, pDefault As PRINTER_DEFAULTS) As Long \par \par Public Enum PrinterAccessRights \par PRINTER_ACCESS_ADMINISTER = &H4 \par PRINTER_ACCESS_USE = &H8 \par PRINTER_ALL_ACCESS = &HF000C \par End Enum \par \par \par You pass the Printer.DeviceName to OpenPrinter this to get the handle. \par \par <-- Use --> \par Dim lret As Long \par Dim pDef As PRINTER_DEFAULTS \par pdef.DesiredAccess = PRINTER_ALL_ACCESS \par \par lret = OpenPrinter(Printer.DeviceName, mhPrinter, pDef) \par \par 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 \par You should check that no error has occured by checking that Err.LastDllError is zero. \par \par 2. Controlling the printer \par \par The printer can be paused and resumed and the jobs may be purged from it using the printer control commands. \par \par <-- Enumerated type --> \par Public Enum Printer_Control_Commands \par PRINTER_CONTROL_PAUSE = 1 \par PRINTER_CONTROL_RESUME = 2 \par PRINTER_CONTROL_PURGE = 3 \par PRINTER_CONTROL_SET_STATUS = 4 \par End Enum \par \par These commands are sent to the printer using the SetPrinter api call. <-- API Declaration --> \par \par Private Declare Function SetPrinterApi Lib "winspool.drv" Alias _ \par "SetPrinterA" (ByVal hPrinter As Long, _ \par ByVal Level As Long, _ \par buffer As Long, _ \par ByVal Command As Long) As Long \par \par Thus the code to control the printer would look like: \par \par <-- Set printer status --> \par Public Sub PrinterCommand (ByVal DeviceName As String, ByVal cmd As Printer_Control_Commands ) \par \par Dim lRet As Long \par Dim mhPrinter As Long \par Dim pDef As Printer_Defaults \par \par '\\\\ Open the printer in admin. mode \par pdef.DesiredAccess = PRINTER_ALL_ACCESS \par lret = OpenPrinter(DeviceName, mhPrinter, pDef) \par \par '\\\\ Send the command \par ' (both Level and Buffer are empty to send commands) \par lRet = SetPrinterApi(mhPrinter, 0, 0,cmd) \par '\\\\ Close the printer \par lRet = ClosePrinter(mhPrinter) \par \par End Sub \par \par \par \par 3. Setting the status of the current job \par \par 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: \par \par Public Sub SetPrinterStatus(ByVal DeviceName As String, ByVal newStatus As Printer_Status) \par \par Dim lRet As Long \par Dim mhPrinter As Long \par Dim pDef As Printer_Defaults \par \par '\\\\ Open the printer in admin. mode \par pdef.DesiredAccess = PRINTER_ALL_ACCESS \par lret = OpenPrinter(DeviceName, mhPrinter, pDef) \par \par '\\\\ Set the new status \par lRet = SetPrinterApi(mhPrinter, newStatus, 0,PRINTER_CONTROL_SET_STATUS) \par '\\\\ Close the printer \par lRet = ClosePrinter(mhPrinter) \par \par End Sub \par \par 4. Changing other properties of the selected printer \par \par 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. \par 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. \par \par In this example we change the comment for the printer: \par \par <-- Using the GetPrinter API call --> \par Dim lret As Long \par Dim SizeNeeded As Long \par \par Dim buffer() As Long \par \par ReDim Preserve buffer(0 To 1) As Long \par lret = GetPrinterApi(mhPrinter, 2, buffer(0), UBound(buffer), SizeNeeded) \par ReDim Preserve buffer(0 To (SizeNeeded / 4) + 3) As Long \par lret = GetPrinterApi(mhPrinter, 2, buffer(0), UBound(buffer) * 4, SizeNeeded) \par \par \par <-- Retrieving the string part --> \par 5. Getting a pointer to a string \par \par 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. \par \par \par \par You can get the memory address (pointer) for any Visual basic string using the undocumented StrPtr function: \par \par lpString = StrPtr(sVar) \par \par 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: \par \par sVar = StrConv(sVar, vbFromUnicode) \par \par Thus the resulting code is: \par \par Dim lpString As Long \par Dim sVar As String \par \par sVar = "New printer comment" \par sVar = StrConv(sVar, vbFromUnicode) \par lpString = StrPtr(sVar) \par buffer(5) = lpString \par '\\\\ Save the new setting to the printer \par lRet = SetPrinter(mhPrinter,2,buffer(0),0) \par } |
Changing the status of the selected printer |
India web developer web development India | India web development company India ecommerce web developer