Re: vb6 print dialog problem
- From: Jack Russell <jackr@xxxxxxxxxxxxxxxxxxxx>
- Date: Wed, 23 Nov 2005 08:45:36 +1100
Mike,
Thanks for that. It is a lot of code to rewrite to use the API. I will try your changing the default printer idea.
If you do find the article it would be good.
Jack Russell
Mike Williams wrote:
"Jack Russell" <jackr@xxxxxxxxxxxxxxxxxxxx> wrote in message news:43838433@xxxxxxxxxxxxxxxxxxxx
If I select a printer it prints to that (and seems to make it the default). If I do the same again without restarting the program and select the other printer it prints to the one I selected the previous time and will continue to do so until I restart the program. In other words it only seems to change the printer selection within the program the first time that I do it.
Somewhere in the back of my mind I seem to recall reading a Knowledge Base article about such behaviour under certain conditions, but I've searched and searched and I can't seem to out my finger on it now.
My refernce to using the API calls is that , using a similar (same but in a different routine) selection dialog the program prints via API calls using the hdc returned by the common dialog. That does select the right printer each time.
Yep. I'm afraid that's what I do all the time now when writing code to reliably select printers. I have almost (but not quite) given up on the VB printer object! Printing to the CommonDialog returned hDC has always worked for me. I'll continue to look for this "half remembered" thing about the printer object "hanging onto" the selected printer until you restart your VB program, but I'm not sure whether I will find it or not. Why don't you just ditch the VB printer object altogether, and do all your printing to the CommonDialog returned hDC? I think that's the route I would take in your position.
Alternatively, how about changing the system wide "default printer" ujsing the API and then using the VB printer object to print to it. You can always save the original default and restore it after your print job if you wish. Here is some code that should change the default printer for you. I don't know whether it is any good for your own specific purposes, but it might be worth looking at taking that route. Paste the example code into a VB Form containing a List Box and a Command Button:
Mike
Option Explicit Private Const HWND_BROADCAST = &HFFFF Private Const WM_WININICHANGE = &H1A Private Const CCHDEVICENAME = 32 Private Const CCHFORMNAME = 32 Private Const STANDARD_RIGHTS_REQUIRED = &HF0000 Private Const PRINTER_ACCESS_ADMINISTER = &H4 Private Const PRINTER_ACCESS_USE = &H8 Private Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _ PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE) Private Const PRINTER_ATTRIBUTE_DEFAULT = 4 Private Const VER_PLATFORM_WIN32_WINDOWS = 1 Private Type OSVERSIONINFO dwOSVersionInfoSize As Long dwMajorVersion As Long dwMinorVersion As Long dwBuildNumber As Long dwPlatformId As Long szCSDVersion As String * 128 End Type Private 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 Private Type PRINTER_INFO_5 pPrinterName As String pPortName As String Attributes As Long DeviceNotSelectedTimeout As Long TransmissionRetryTimeout As Long End Type Private Type PRINTER_DEFAULTS pDatatype As Long pDevMode As Long DesiredAccess As Long End Type Private 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 Private Declare Function WriteProfileString _ Lib "kernel32" Alias "WriteProfileStringA" _ (ByVal lpszSection As String, _ ByVal lpszKeyName As String, _ ByVal lpszString As String) As Long Private Declare Function SendMessage Lib "user32" _ Alias "SendMessageA" (ByVal hwnd As Long, _ ByVal wMsg As Long, _ ByVal wParam As Long, _ lparam As String) As Long Private Declare Function GetVersionExA Lib "kernel32" _ (lpVersionInformation As OSVERSIONINFO) As Integer Private Declare Function OpenPrinter Lib "winspool.drv" _ Alias "OpenPrinterA" _ (ByVal pPrinterName As String, _ phPrinter As Long, _ pDefault As PRINTER_DEFAULTS) As Long Private 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 Private 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 Private Declare Function lstrcpy Lib "kernel32" _ Alias "lstrcpyA" _ (ByVal lpString1 As String, _ ByVal lpString2 As Any) As Long Private Declare Function ClosePrinter Lib "winspool.drv" _ (ByVal hPrinter As Long) As Long
Private 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
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 ' handle errors here 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 ' handle errors here 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 Form_Load() Dim r As Long Dim Buffer As String Buffer = Space(8192) r = GetProfileString("PrinterPorts", vbNullString, "", _ Buffer, Len(Buffer)) ParseList List1, Buffer 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
.
- Follow-Ups:
- Re: vb6 print dialog problem
- From: Randy Birch
- Re: vb6 print dialog problem
- References:
- vb6 print dialog problem
- From: Jack Russell
- Re: vb6 print dialog problem
- From: mike williams
- Re: vb6 print dialog problem
- From: Jack Russell
- Re: vb6 print dialog problem
- From: Mike Williams
- vb6 print dialog problem
- Prev by Date: Re: Text overlay on image then Save to JPEG with reasonable DPI for Online printshop
- Next by Date: Default e-mail & browser
- Previous by thread: Re: vb6 print dialog problem
- Next by thread: Re: vb6 print dialog problem
- Index(es):