This article shows how to programmatically set which printer is the system default printer. Not all applications or components can select a specific printer to use. This often makes it necessary to change the default printer for the system so that the application or component will use the desired printer.
The following code sample provides a means to determine which printers are available, and to designate one as the system default printer.
Step-by-Step Example
- Start a new Standard EXE project in Visual Basic. Form1 is created by default. - Add a new module to the project and insert the following code:
Module1.bas |
Click here to copy the following block | Public Const HWND_BROADCAST = &HFFFF Public Const WM_WININICHANGE = &H1A
Public Const CCHDEVICENAME = 32 Public Const CCHFORMNAME = 32
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000 Public Const PRINTER_ACCESS_ADMINISTER = &H4 Public Const PRINTER_ACCESS_USE = &H8 Public Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _ PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)
Public Const PRINTER_ATTRIBUTE_DEFAULT = 4
Public Const VER_PLATFORM_WIN32_WINDOWS = 1
Public Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 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 dmICMMethod As Long dmICMIntent As Long dmMediaType As Long dmDitherType As Long dmReserved1 As Long dmReserved2 As Long End Type
Public Type PRINTER_INFO_5 pPrinterName As String pPortName As String Attributes As Long DeviceNotSelectedTimeout As Long TransmissionRetryTimeout As Long End Type
Public Type PRINTER_DEFAULTS pDatatype As Long pDevMode As Long DesiredAccess As Long End Type
Declare Function GetProfileString Lib "kernel32" _ Alias "GetProfileStringA" _ (ByVal lpAppName As String, _ ByVal lpKeyName As String, _ ByVal lpDefault As String, _ ByVal lpReturnedString As String, _ ByVal nSize As Long) As Long
Declare Function WriteProfileString Lib "kernel32" _ Alias "WriteProfileStringA" _ (ByVal lpszSection As String, _ ByVal lpszKeyName As String, _ ByVal lpszString As String) As Long
Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" _ (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lparam As String) As Long
Declare Function GetVersionExA Lib "kernel32" _ (lpVersionInformation As OSVERSIONINFO) As Integer
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 SetPrinter Lib "winspool.drv" _ Alias "SetPrinterA" _ (ByVal hPrinter As Long, _ ByVal Level As Long, _ pPrinter As Any, _ ByVal Command 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 lstrcpy Lib "kernel32" _ Alias "lstrcpyA" _ (ByVal lpString1 As String, _ ByVal lpString2 As Any) As Long
Public Declare Function ClosePrinter Lib "winspool.drv" _ (ByVal hPrinter As Long) As Long
Public Sub SelectPrinter(NewPrinter As String) Dim Prt As Printer
For Each Prt In Printers If Prt.DeviceName = NewPrinter Then Set Printer = Prt Exit For End If Next End Sub |
- Place a ListBox and a CommandButton on Form1. - Add the following code to the General Declarations section of Form1:
Form1.frm |
Click here to copy the following block | Option Explicit
Private Function PtrCtoVbString(Add As Long) As String Dim sTemp As String * 512, x As Long
x = lstrcpy(sTemp, Add) If (InStr(1, sTemp, Chr(0)) = 0) Then PtrCtoVbString = "" Else PtrCtoVbString = Left(sTemp, InStr(1, sTemp, Chr(0)) - 1) End If End Function
Private Sub SetDefaultPrinter(ByVal PrinterName As String, _ ByVal DriverName As String, ByVal PrinterPort As String) Dim DeviceLine As String Dim r As Long Dim l As Long DeviceLine = PrinterName & "," & DriverName & "," & PrinterPort r = WriteProfileString("windows", "Device", DeviceLine) l = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, "windows") End Sub
Private Sub Win95SetDefaultPrinter() Dim Handle As Long Dim PrinterName As String Dim pd As PRINTER_DEFAULTS Dim x As Long Dim need As Long Dim pi5 As PRINTER_INFO_5 Dim LastError As Long
PrinterName = List1.List(List1.ListIndex) If PrinterName = "" Then Exit Sub End If
pd.pDatatype = 0& pd.DesiredAccess = PRINTER_ALL_ACCESS Or pd.DesiredAccess
x = OpenPrinter(PrinterName, Handle, pd) If x = False Then Exit Sub End If
x = GetPrinter(Handle, 5, ByVal 0&, 0, need) ReDim t((need \ 4)) As Long
x = GetPrinter(Handle, 5, t(0), need, need) If x = False Then Exit Sub End If
pi5.pPrinterName = PtrCtoVbString(t(0)) pi5.pPortName = PtrCtoVbString(t(1)) pi5.Attributes = t(2) pi5.DeviceNotSelectedTimeout = t(3) pi5.TransmissionRetryTimeout = t(4)
pi5.Attributes = PRINTER_ATTRIBUTE_DEFAULT
x = SetPrinter(Handle, 5, pi5, 0)
If x = False Then MsgBox "SetPrinter Failed. Error code: " & Err.LastDllError Exit Sub Else If Printer.DeviceName <> List1.Text Then SelectPrinter (List1.Text) End If End If
ClosePrinter (Handle) End Sub
Private Sub GetDriverAndPort(ByVal Buffer As String, DriverName As _ String, PrinterPort As String)
Dim iDriver As Integer Dim iPort As Integer DriverName = "" PrinterPort = ""
iDriver = InStr(Buffer, ",") If iDriver > 0 Then
DriverName = Left(Buffer, iDriver - 1)
iPort = InStr(iDriver + 1, Buffer, ",")
If iPort > 0 Then PrinterPort = Mid(Buffer, iDriver + 1, _ iPort - iDriver - 1) End If End If End Sub
Private Sub ParseList(lstCtl As Control, ByVal Buffer As String) Dim i As Integer Dim s As String
Do i = InStr(Buffer, Chr(0)) If i > 0 Then s = Left(Buffer, i - 1) If Len(Trim(s)) Then lstCtl.AddItem s Buffer = Mid(Buffer, i + 1) Else If Len(Trim(Buffer)) Then lstCtl.AddItem Buffer Buffer = "" End If Loop While i > 0 End Sub
Private Sub WinNTSetDefaultPrinter() Dim Buffer As String Dim DeviceName As String Dim DriverName As String Dim PrinterPort As String Dim PrinterName As String Dim r As Long If List1.ListIndex > -1 Then Buffer = Space(1024) PrinterName = List1.Text r = GetProfileString("PrinterPorts", PrinterName, "", _ Buffer, Len(Buffer))
GetDriverAndPort Buffer, DriverName, PrinterPort
If DriverName <> "" And PrinterPort <> "" Then SetDefaultPrinter List1.Text, DriverName, PrinterPort If Printer.DeviceName <> List1.Text Then SelectPrinter (List1.Text) End If End If End If End Sub
Private Sub Command1_Click() Dim osinfo As OSVERSIONINFO Dim retvalue As Integer
osinfo.dwOSVersionInfoSize = 148 osinfo.szCSDVersion = Space$(128) retvalue = GetVersionExA(osinfo)
If osinfo.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS Then Call Win95SetDefaultPrinter Else Call WinNTSetDefaultPrinter End If End Sub
Private Sub Form_Load() Dim r As Long Dim Buffer As String Command1.Caption = "<< Set as Default Printer" Buffer = Space(8192) r = GetProfileString("PrinterPorts", vbNullString, "", _ Buffer, Len(Buffer))
ParseList List1, Buffer End Sub |
- Run the project and note that the preceding code populates a ListBox with all available printers. - Select one printer in the list and make it the default by clicking the CommandButton. - Confirm that the default printer has changed: On the Start button, select Settings, select Printers, and then check which printer is marked as the default. Alternatively, you can print to the default printer from any application on your system. |
|