[blue]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 ClosePrinter Lib "winspool.drv" (ByVal hPrinter As Long) As Long
Public Declare Function DocumentProperties Lib "winspool.drv" Alias "DocumentPropertiesA" (ByVal hwnd As Long, ByVal hPrinter As Long, ByVal pDeviceName As String, pDevModeOutput As Any, pDevModeInput As Any, ByVal fMode As Long) As Long
Public Declare Function GetPrinter Lib "winspool.drv" Alias "GetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Any, ByVal cbBuf As Long, pcbNeeded As Long) As Long
Public Declare Function SetPrinter Lib "winspool.drv" Alias "SetPrinterA" (ByVal hPrinter As Long, ByVal Level As Long, pPrinter As Byte, ByVal Command As Long) As Long
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Public Const CCHDEVICENAME = 32
Public Const CCHFORMNAME = 32
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
dmUnusedPadding As Integer
dmBitsPerPel As Long
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Public Type PRINTER_DEFAULTS
pDatatype As String
pDevMode As DEVMODE
DesiredAccess As Long
End Type
Public Type PRINTER_INFO_2
pServerName As String
pPrinterName As String
pShareName As String
pPortName As String
pDriverName As String
pComment As String
pLocation As String
pDevMode As Long 'DEVMODE
pSepFile As String
pPrintProcessor As String
pDatatype As String
pParameters As String
pSecurityDescriptor As Long 'SECURITY_DESCRIPTOR
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 PRINTER_ACCESS_ADMINISTER = &H4
Public Const PRINTER_ACCESS_USE = &H8
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
Public Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
Public Const DM_MODIFY = 8
Public Const DM_PROMPT = 4
Public Const DM_COPY = 2
Public Const DM_IN_BUFFER = DM_MODIFY
Public Const DM_IN_PROMPT = DM_PROMPT
Public Const DM_OUT_BUFFER = DM_COPY
Public Enum CLP_SETTINGS_LOCATION
PagesPerSide = 478
PosterLayout = 492
LayoutType = 504
End Enum
' Simplistic version. We assume we only want to change one byte at a time in the
' DriverExtra memory
Public Function SetDriverExtraByte(lLocation As CLP_SETTINGS_LOCATION, bValue As Byte)
'Dim PrintDevIn As DEVMODE
Dim PrintDevOut As DEVMODE ' Just needed for sizing purposes
Dim phPrinter As Long
Dim printerDefaults As PRINTER_DEFAULTS
Dim pBuffer() As Byte
Dim pcbNeeded As Long
Dim pinfo As PRINTER_INFO_2
'Dim ExtraBuffer As String
Dim result As Long
'Dim BufferIn() As Byte
Dim BufferOut() As Byte
'Dim PrivateBuffer() As Byte
'Dim CompareBuffer() As Byte
' Get required access to the printer
printerDefaults.DesiredAccess = PRINTER_ALL_ACCESS
If OpenPrinter(Printer.DeviceName, phPrinter, printerDefaults) Then ' Note we are working with whatever VB thinks is the default printer in this example
' See how much data there is for this printer (DEVMODE + private data that comes after it) ...
result = DocumentProperties(0&, phPrinter, Printer.DeviceName, 0&, 0&, 0)
'... and size our own buffer appropriately
'ReDim BufferIn(result - 1) As Byte
ReDim BufferOut(result - 1) As Byte
' Now it is safe to read the data, which is basically the current printer settings that you would
' normally access through the print setup dialogs including any special features
result = DocumentProperties(0&, phPrinter, Printer.DeviceName, BufferOut(0), 0&, DM_OUT_BUFFER)
' Ok, modify the private data (advanced features of the specific printer)
BufferOut(lLocation + Len(PrintDevOut)) = bValue
' In theory it is suggested we ensure BufferOut is legit by another call to DocumentProperties as shown below. In practice,
' for this example it does not seem to be necessary
'result = DocumentProperties(0&, phPrinter, Printer.DeviceName, BufferOut(0), BufferOut(0), DM_IN_BUFFER Or DM_OUT_BUFFER)
' Now we need to drop our modified DEVMODE+private data into a legit PRINTER_INFO_2 structure to reconfigure the driver
GetPrinter phPrinter, 2, 0&, 0&, pcbNeeded ' find out how big buffer needs to be
ReDim pBuffer(pcbNeeded) As Byte ' Ok, make sure buffer is big enough
GetPrinter phPrinter, 2, pBuffer(0), pcbNeeded, pcbNeeded ' get printer info into buffer
CopyMemory pinfo, pBuffer(0), Len(pinfo) 'First part of buffer is basic PRINTER_INFO_2 structure
pinfo.pDevMode = VarPtr(BufferOut(0)) ' and we need that so we can set the DevMode member to point to our modified DevMode
CopyMemory pBuffer(0), pinfo, Len(pinfo) 'then copy it back into the buffer
' And here's were we change it ...
SetPrinter phPrinter, 2, pBuffer(0), 0& ' and set the printer using our updated info
End If
ClosePrinter phPrinter
'Ta da - all done
End Function[/blue]