Re: Windows Default Printer not being Reset
- From: "jkotuby" <jkotuby@xxxxxxxx>
- Date: Thu, 2 Mar 2006 07:47:57 -0500
Mike,
Thank you for the excellent code. I will take what I can use to quickly
remedy the problem. Your positioning code is superb.
I guess where I went wrong was that I assumed that by presenting the
PrinterDialog box to the user to simply select a printer it would just set
the VB.Printer object. I had no intention of changing the Windows Default
printer in the first place. Why would Microsoft force the CommonDialog
control t o change the Windows Default printer if it provided no easy
mechanism in VB for resetting the original default?
I guess I must study your code more thoroughly first. Maybe you are showing
me a way to use the dialog control such that it does not affect the Windows
Default printer.
Right now I need to get ready to head out to the office.
Thanks again......
"Mike Williams" <Mike@xxxxxxxxxxxxxxxxx> wrote in message
news:uWPfATfPGHA.420@xxxxxxxxxxxxxxxxxxxxxxx
"jkotuby" <jkotuby@xxxxxxxx> wrote in message
news:eXNGQGfPGHA.3260@xxxxxxxxxxxxxxxxxxxxxxx
[lots of stuff snipped] Dim x as Printer
For each x in Printers()
If x.Devicename = mnPtrDefaultName
Set Printer = x
End If
Next
This does not work either. Can anybody help with this problem?
The documentaion seems to indicate that either of these methods
will reset the Windows Default printer.
The above code does not set the Windows default printer. It sets the VB
printer object. There are ways of setting the default printer though, and
I'll post some code for you if you want to do that, but personally I
wouldn't do it that way. It's just a personal thing of course, but I don't
believe in altering the default printer at all, even for short periods and
even if you are going to set it back afterwards. It is better (in my
opinion) to "point the VB printer object at the printer you wish to use"
and leave the default printer setting alone. There are all sorts of ways
of doing this. In fact you'll find some suitable code on Microsofts MSDN
pages, However, that code uses a separate dll. I personally don't believe
in adding extra libraries to my projects unless there is no other way.
Here is a version of the MS code that I have modified in a few ways
(firstly by using an old version of their code that does not use the dll
and secondly by adding some extra useful functionality, such as very
accurate location of your printed output on the page, regardless of the
size or location of the current printer's "unprintable margins"). Here is
some code. To try it, start a new VB project (just one Form containing one
Command Button) and paste in the following code:
Mike
Option Explicit
Private Const OUT_DEFAULT_PRECIS = 0
Private Const CLIP_DEFAULT_PRECIS = 0
Private Const DEFAULT_QUALITY = 0
Private Const DEFAULT_PITCH = 0
Private Const FF_ROMAN = 16
Private Const CCHDEVICENAME = 32
Private Const CCHFORMNAME = 32
Private Const GMEM_MOVEABLE = &H2
Private Const GMEM_ZEROINIT = &H40
Private Const DM_DUPLEX = &H1000&
Private Const DM_ORIENTATION = &H1&
Private Const DM_PAPERSIZE = &H2&
Private Const PD_PRINTSETUP = &H40
Private Const PD_RETURNDC = &H100
Private Const PD_DISABLEPRINTTOFILE = &H80000
Private Const PHYSICALOFFSETX As Long = 112
Private Const PHYSICALOFFSETY As Long = 113
Private Const OPAQUE = 0
Private Const TRANSPARENT = 1
Private Type POINTAPI
x As Long
y As Long
End Type
Private Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
Private Type PRINTDLG_TYPE
lStructSize As Long
hwndOwner As Long
hDevMode As Long
hDevNames As Long
hdc As Long
flags As Long
nFromPage As Integer
nToPage As Integer
nMinPage As Integer
nMaxPage As Integer
nCopies As Integer
hInstance As Long
lCustData As Long
lpfnPrintHook As Long
lpfnSetupHook As Long
lpPrintTemplateName As String
lpSetupTemplateName As String
hPrintTemplate As Long
hSetupTemplate As Long
End Type
Private Type DEVNAMES_TYPE
wDriverOffset As Integer
wDeviceOffset As Integer
wOutputOffset As Integer
wDefault As Integer
extra As String * 100
End Type
Private Type DEVMODE_TYPE
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 Integer
dmPelsWidth As Long
dmPelsHeight As Long
dmDisplayFlags As Long
dmDisplayFrequency As Long
End Type
Private Declare Function GetDeviceCaps Lib "gdi32" _
(ByVal hdc As Long, ByVal nindex As Long) As Long
Private Declare Function PrintDialog Lib "comdlg32.dll" _
Alias "PrintDlgA" (pPrintdlg As PRINTDLG_TYPE) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (hpvDest As Any, hpvSource As Any, _
ByVal cbCopy As Long)
Private Declare Function GlobalLock Lib "kernel32" _
(ByVal hMem As Long) As Long
Private Declare Function GlobalUnlock Lib "kernel32" _
(ByVal hMem As Long) As Long
Private Declare Function GlobalAlloc Lib "kernel32" _
(ByVal wFlags As Long, ByVal dwBytes As Long) As Long
Private Declare Function GlobalFree Lib "kernel32" _
(ByVal hMem As Long) As Long
Private Declare Function SetBkMode Lib "gdi32" _
(ByVal hdc As Long, ByVal nBkMode As Long) As Long
Private Sub SetPrinterOrigin(x As Single, y As Single)
With Printer
.ScaleLeft = .ScaleX(GetDeviceCaps(.hdc, PHYSICALOFFSETX), _
vbPixels, .ScaleMode) - x
.ScaleTop = .ScaleY(GetDeviceCaps(.hdc, PHYSICALOFFSETY), _
vbPixels, .ScaleMode) - y
.CurrentX = 0
.CurrentY = 0
End With
End Sub
Private Function PrintReport(frmOwner As Form, Optional _
InitialPrinter As String, Optional PrintFlags As Long) _
As Boolean
Dim PrintDlg As PRINTDLG_TYPE
Dim DevMode As DEVMODE_TYPE
Dim DevName As DEVNAMES_TYPE
Dim lpDevMode As Long, lpDevName As Long
Dim bReturn As Integer, OriginalPrinter As String
Dim objPrinter As Printer, NewPrinterName As String
PrintDlg.lStructSize = Len(PrintDlg)
PrintDlg.hwndOwner = frmOwner.hWnd
PrintDlg.flags = PrintFlags
On Error Resume Next
' save the current VB printer device name in case the user
' presses cancel and we need to restore it
OriginalPrinter = Printer.DeviceName
' Set the initial printer in the dialog
If Len(InitialPrinter) > 0 Then
For Each objPrinter In Printers
If InStr(1, objPrinter.DeviceName, InitialPrinter, _
vbTextCompare) > 0 Then
Set Printer = objPrinter
Exit For
End If
Next
End If
'
DevMode.dmDeviceName = Printer.DeviceName
DevMode.dmSize = Len(DevMode)
' Must set the appropriate flag in the dmFields entry for
' any setting you wish to use (there are loads of 'em, see
' API Viewer)
DevMode.dmFields = DM_ORIENTATION Or DM_PAPERSIZE
'DevMode.dmPaperWidth = Printer.Width
DevMode.dmOrientation = Printer.Orientation 'vbPRORLandscape
DevMode.dmPaperSize = Printer.PaperSize 'vbPRPSEnv10
'DevMode.dmDuplex = Printer.Duplex
On Error GoTo 0
PrintDlg.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or _
GMEM_ZEROINIT, Len(DevMode))
lpDevMode = GlobalLock(PrintDlg.hDevMode)
If lpDevMode > 0 Then
CopyMemory ByVal lpDevMode, DevMode, Len(DevMode)
bReturn = GlobalUnlock(PrintDlg.hDevMode)
End If
With DevName
.wDriverOffset = 8
.wDeviceOffset = .wDriverOffset + 1 + Len _
(Printer.DriverName)
.wOutputOffset = .wDeviceOffset + 1 + Len(Printer.Port)
.wDefault = 0
End With
With Printer
DevName.extra = .DriverName & Chr(0) & _
.DeviceName & Chr(0) & .Port & Chr(0)
End With
PrintDlg.hDevNames = GlobalAlloc(GMEM_MOVEABLE Or _
GMEM_ZEROINIT, Len(DevName))
lpDevName = GlobalLock(PrintDlg.hDevNames)
If lpDevName > 0 Then
CopyMemory ByVal lpDevName, DevName, Len(DevName)
bReturn = GlobalUnlock(lpDevName)
End If
If PrintDialog(PrintDlg) <> 0 Then
DoEvents ' allow the dialog to remove itself from the display
Me.Refresh
PrintReport = True
lpDevName = GlobalLock(PrintDlg.hDevNames)
CopyMemory DevName, ByVal lpDevName, 45
bReturn = GlobalUnlock(lpDevName)
GlobalFree PrintDlg.hDevNames
lpDevMode = GlobalLock(PrintDlg.hDevMode)
CopyMemory DevMode, ByVal lpDevMode, Len(DevMode)
bReturn = GlobalUnlock(PrintDlg.hDevMode)
GlobalFree PrintDlg.hDevMode
NewPrinterName = UCase$(Left(DevMode.dmDeviceName, _
InStr(DevMode.dmDeviceName, Chr$(0)) - 1))
If UCase(Printer.DeviceName) <> NewPrinterName Then
For Each objPrinter In Printers
If UCase$(objPrinter.DeviceName) = NewPrinterName Then
Set Printer = objPrinter
End If
Next
End If
'
On Error Resume Next
Printer.Copies = DevMode.dmCopies
Printer.Duplex = DevMode.dmDuplex
Printer.Orientation = DevMode.dmOrientation
Printer.PaperSize = DevMode.dmPaperSize
Printer.PrintQuality = DevMode.dmPrintQuality
Printer.ColorMode = DevMode.dmColor
Printer.PaperBin = DevMode.dmDefaultSource
'
' Mike's Note: One or other of the above printer settings
' is setting the printer font to opaque (even though the
' value of Printer.FontTransparent remains True). This might
' not happen on all printers, but it needs fixing anyway so
' I have now added the following line to set the font back
' to transparent.
SetBkMode Printer.hdc, TRANSPARENT
'
On Error GoTo 0
Else
PrintReport = False ' user cancelled
For Each objPrinter In Printers
If objPrinter.DeviceName = OriginalPrinter Then
Set Printer = objPrinter
Exit For
End If
Next
GlobalFree PrintDlg.hDevNames
GlobalFree PrintDlg.hDevMode
End If
End Function
Private Sub Command1_Click()
' Display a printer dialog which starts off with any
' initial printer we wish. In this example we use the
' first Epson printer that we find. If the specified
' printer is not found then the dialog opens showing
' the current default printer (If you want to start
' showing the default then you can either modify the
' routine so as to cause the first For Each loop is not
' executed or, more simply, use something like:
' PrintReport, Me, "start with the default printer"
If PrintReport(Me, "Epson") = False Then
' If PrintReport(Me, "Epson", PD_RETURNDC) = False Then
Caption = "cancelled"
Exit Sub ' user cancelled
End If
' ******** Print your document here ********
' The following line sets the origin (0, 0) to the top left
' corner of the physical page on all printers instead of to
' the top left corner of the "printable area" (the default).
' This enables you to position stuff accurately on the page
' whatever printer you are using.
Printer.ScaleMode = vbInches
SetPrinterOrigin 0, 0
'
Printer.Font.Name = "Times New Roman"
Printer.Font.Size = 12
' set the line thickness to about 3 thousandths of an inch
Printer.DrawWidth = Printer.ScaleX(0.003, vbInches, vbPixels)
' draw a 1 x 4 inch rectangle at location (1, 1)
Printer.Line (1, 1)-(1 + 4, 1 + 1), , B
' Draw some text at location (1, 3)
Printer.CurrentX = 1: Printer.CurrentY = 3
Printer.Print "Whisky and Coke®"
Printer.EndDoc
End Sub
.
- Follow-Ups:
- Re: Windows Default Printer not being Reset
- From: Mike Williams
- Re: Windows Default Printer not being Reset
- References:
- Windows Default Printer not being Reset
- From: jkotuby
- Re: Windows Default Printer not being Reset
- From: Mike Williams
- Windows Default Printer not being Reset
- Prev by Date: Re: Windows Default Printer not being Reset
- Next by Date: Re: Quick utility? Automatically close folder on icon open.
- Previous by thread: Re: Windows Default Printer not being Reset
- Next by thread: Re: Windows Default Printer not being Reset
- Index(es):