From: M Wade on 15 Jun 2010 17:40 I have an application that printed multiple pages and I have a printer (BROTHER 5370DW) that allows this. I select the printer using the CommonDialog1.ShowPrinter command and then click on the printer preferences to select two-sided printing. However, when the actual printing takes place is does not print two-sided. Is there something in VB print methods that would over-ride this option or not allow it? Marv
From: Shotgun Thom on 16 Jun 2010 00:08 On Jun 15, 2:40 pm, M Wade <nowh...(a)columbus.rr.com> wrote: > I have an application that printed multiple pages and I have a printer > (BROTHER 5370DW) that allows this. I select the printer using the > CommonDialog1.ShowPrinter command and then click on the printer > preferences to select two-sided printing. However, when the actual > printing takes place is does not print two-sided. > > Is there something in VB print methods that would over-ride this option > or not allow it? > > Marv Hi Marv: While the VB6 Printer Object has a duplex setting (Printer.Duplex) I don't believe the CommonDialog has that property. Sooo... you need to Apply the setting using your Brother Print Setup. I know you think you are doing that now by clicking on the Printer Preferences button... but unfortunately it doesn't get translated to the print object or to common dialog. The answer is to right click on the Brother printer icon in the print dialog and choose Printer Preferences from the context menu that pops up. You'll note in this option an "Apply":button magically appears in the setup window. After you've set your options then click Apply, then Ok. Now the duplex thing should work. You'll need to go back to undo duplex when finished since that has now become the default. The Apply button only appears when choosing Printing Preferences from the context menu. It is not available if you just click the Preference button. The other way would be to create your own duplex option variable. A value of 1 is simplex (singled sided), 2 is double sided horizontal and 3 is double sided vertical. Tom
From: Mike Williams on 16 Jun 2010 12:52 "M Wade" <nowhere(a)columbus.rr.com> wrote in message news:us2krNNDLHA.3492(a)TK2MSFTNGP02.phx.gbl... > I have an application that printed multiple pages and > I have a printer (BROTHER 5370DW) that allows this. > I select the printer using the CommonDialog1.ShowPrinter > command and then click on the printer preferences to select > two-sided printing. However, when the actual printing > takes place is does not print two-sided. Is there something > in VB print methods that would over-ride this option or not allow it? Under normal usage (from WinXP onwards) the CommonDialog Control changes only the printer to be used and not any of its properties (although the user can on most systems manually edit the properties in the dialog by right clicking as suggested by Shotgun Thom, but in that case you need to specifically advise your user to do something that he would not normally do and those edits would "stick" beyond your own application and become the default properties for all applications unless you asked your user to specifically negate them afterwards, and for both of those reasons it is not something I would advise). If you want to change the VB Printer Object's properties to those selected by the user in the CommonDialog then you need to transfer them from the CommonDialog properties to the equivalent VB Printer Object properties. However, the CommonDialog Control does not have a Duplex property and so you cannot do that in this specific case. In any case, I would personally advise against using the CommonDialog in the normal way anyway, because when the user selects a printer in it then that printer becomes the user's new system default printer (unless you set the PrinterDefault property to False, which in most cases defeats the object altogether). This is not how most applications behave. The best way is to allow your user to select the desired printer and for that printer to be used only for your own VB application, without it altering the user's system default printer or any of its default properties. Of all the available methods (of which there are many) the one I would advise you to use is to display a printer dialog (using either the CommonDialog Control or the equivalent API dialog) and ask it to return a DC for you. Your VB application can then print to that returned DC safe in the knowledge that the printer will be set up /exactly/ as the user has selected in the printer dialog, including all of the sometimes rather esoteric settings that certain specialist printers have and that are simply not accessible by any other means (for example, the "use metallic gold ribbon" setting on a Citizen Printiva printer, which is something that Windows itself knows nothing about). That is by far the best method, and it is essentially the method used by most professional applications. The problem with this method of course is that you cannot effectively use it with the VB Printer Object and so you will need to perform all your printing output using the equivalent API printing methods. It is however what I would advise. If you woud prefer to stick with the VB Printer Object then there are other methods you can use to display a dialog that returns more information for you than does the CommonDialog Control, and that avoids the "printer settings sticks as the default" problem and allows your use to select from most of the common properties, including your own desired duplex printing option. Your code can then transfer those settings to the VB printer Object for printing. There is a Micro$oft DLL that can help you to do this (from memory I think it is called msvbprndlg.dll or something similar) but you can do the same sort of thing without needing to package a DLL by using standard API dialog calls, although you need to take account of the fact that some printers (probably mostly network printers) have a device name that is longer than the standard maximum 32 character length for dmDeviceName in the DEVMODE structure and so you need to make sure that your code takes account of such a possibility. As they say in all the best TV cookery programs, here's something I prepared earlier (see below) ;-) Printing is still an evolving thing of course, and so if this code does not work for your specific printer then perhaps you might like to consider my other suggestion (asking the printer dialog to return a DC for you and printing to that DC using API printing methods, which will definitely work as long as your printer driver is installed properly). If you have any problems then post again, although I imagine that the following code will probably do the trick for you (paste it into a VB Form): Mike Option Explicit 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 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 PD_PRINTSETUP = &H40 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 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 * 200 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 dmICMMethod As Long dmICMIntent As Long dmMediaType As Long dmDitherType As Long dmReserved1 As Long dmReserved2 As Long dmPanningWidth As Long dmPanningHeight As Long End Type 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 SelectPrinter(frmOwner As Form, Optional _ InitialPrinter As String, Optional _ PrintFlags As Long = PD_PRINTSETUP) _ As Boolean Dim LongPrinterName As String 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 p1 As Printer, NewPrinterName As String PrintDlg.lStructSize = Len(PrintDlg) PrintDlg.hwndOwner = frmOwner.hWnd PrintDlg.flags = PrintFlags On Error Resume Next OriginalPrinter = Printer.DeviceName If Len(InitialPrinter) > 0 Then For Each p1 In Printers If InStr(1, p1.DeviceName, InitialPrinter, _ vbTextCompare) > 0 Then Set Printer = p1 Exit For End If Next End If DevMode.dmDeviceName = Printer.DeviceName DevMode.dmSize = Len(DevMode) DevMode.dmFields = DM_ORIENTATION DevMode.dmPaperWidth = Printer.Width DevMode.dmOrientation = Printer.Orientation DevMode.dmPaperSize = Printer.PaperSize 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 CopyMemory DevName, ByVal lpDevName, Len(DevName) LongPrinterName = Mid$(DevName.extra, _ DevName.wDeviceOffset - DevName.wDriverOffset + 1) LongPrinterName = Left$(LongPrinterName, _ InStr(LongPrinterName, Chr$(0)) - 1) DoEvents ' allow dialog to remove itself from display Me.Refresh SelectPrinter = 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 Printer.DeviceName <> _ LongPrinterName Then For Each p1 In Printers If p1.DeviceName = _ LongPrinterName Then Set Printer = p1 End If Next End If On Error Resume Next ' Transfer settings from the Devmode structure to the ' VB printer object (this example just transfers some ' of them but you can of course use transfer more) 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 SetBkMode Printer.hdc, TRANSPARENT ' On Error GoTo 0 Else SelectPrinter = False ' user cancelled For Each p1 In Printers If p1.DeviceName = OriginalPrinter Then Set Printer = p1 Exit For End If Next GlobalFree PrintDlg.hDevNames GlobalFree PrintDlg.hDevMode End If End Function Private Sub Command1_Click() ' Note: Specifying Printer.DeviceName in the following ' line will start the dialog off with the default ' printer initially selected in the selection box, but ' you can use any other string you wish. For example, ' using "Epson" will cause the dialog to start with ' the first printer it finds with the word "Epson" ' in its device name. If SelectPrinter(Me, Printer.DeviceName) Then Printer.TrackDefault = False Printer.ScaleMode = vbInches ' set origin to top left corner of physical page ' (otherwise it would be the top left corner of ' the printable area, which is not the same) SetPrinterOrigin 0, 0 Printer.CurrentX = 1: Printer.CurrentY = 1 Printer.Print "Hello World" Printer.EndDoc End If End Sub
From: M Wade on 16 Jun 2010 13:54 Mike,I much appreciate you response and that from Shotgun Thom. My use of VB6 is almost totally for my own use and some I have developed for churches and a privately owned travel agency, so I am not a professional programmer. The specific program I am working on now is to catalog books and being able to search by author's name,Book Series and Book Title. If I print all of the entries it could go quite a few pages, hence the desire to use the duplex capability of the printer which is a network device. I can easily change the printer setting before running the program and reset it after the printing is done but I am interested enough to want to try something within the program. At age 77 and long retired I have the time to do that (hopefully). I am not very clear on using APIs and haven't the foggiest idea what the reference to DC is, but I am going to see if I can understand the code you supplied. Thanks again. Marv On 6/16/2010 12:52 PM, Mike Williams wrote: > "M Wade"<nowhere(a)columbus.rr.com> wrote in message > news:us2krNNDLHA.3492(a)TK2MSFTNGP02.phx.gbl... > >> I have an application that printed multiple pages and >> I have a printer (BROTHER 5370DW) that allows this. >> I select the printer using the CommonDialog1.ShowPrinter >> command and then click on the printer preferences to select >> two-sided printing. However, when the actual printing >> takes place is does not print two-sided. Is there something >> in VB print methods that would over-ride this option or not allow it? > > Under normal usage (from WinXP onwards) the CommonDialog Control changes > only the printer to be used and not any of its properties (although the user > can on most systems manually edit the properties in the dialog by right > clicking as suggested by Shotgun Thom, but in that case you need to > specifically advise your user to do something that he would not normally do > and those edits would "stick" beyond your own application and become the > default properties for all applications unless you asked your user to > specifically negate them afterwards, and for both of those reasons it is not > something I would advise). > > If you want to change the VB Printer Object's properties to those selected > by the user in the CommonDialog then you need to transfer them from the > CommonDialog properties to the equivalent VB Printer Object properties. > However, the CommonDialog Control does not have a Duplex property and so you > cannot do that in this specific case. In any case, I would personally advise > against using the CommonDialog in the normal way anyway, because when the > user selects a printer in it then that printer becomes the user's new system > default printer (unless you set the PrinterDefault property to False, which > in most cases defeats the object altogether). This is not how most > applications behave. The best way is to allow your user to select the > desired printer and for that printer to be used only for your own VB > application, without it altering the user's system default printer or any of > its default properties. > > Of all the available methods (of which there are many) the one I would > advise you to use is to display a printer dialog (using either the > CommonDialog Control or the equivalent API dialog) and ask it to return a DC > for you. Your VB application can then print to that returned DC safe in the > knowledge that the printer will be set up /exactly/ as the user has selected > in the printer dialog, including all of the sometimes rather esoteric > settings that certain specialist printers have and that are simply not > accessible by any other means (for example, the "use metallic gold ribbon" > setting on a Citizen Printiva printer, which is something that Windows > itself knows nothing about). That is by far the best method, and it is > essentially the method used by most professional applications. The problem > with this method of course is that you cannot effectively use it with the VB > Printer Object and so you will need to perform all your printing output > using the equivalent API printing methods. It is however what I would > advise. > > If you woud prefer to stick with the VB Printer Object then there are other > methods you can use to display a dialog that returns more information for > you than does the CommonDialog Control, and that avoids the "printer > settings sticks as the default" problem and allows your use to select from > most of the common properties, including your own desired duplex printing > option. Your code can then transfer those settings to the VB printer Object > for printing. > > There is a Micro$oft DLL that can help you to do this (from memory I think > it is called msvbprndlg.dll or something similar) but you can do the same > sort of thing without needing to package a DLL by using standard API dialog > calls, although you need to take account of the fact that some printers > (probably mostly network printers) have a device name that is longer than > the standard maximum 32 character length for dmDeviceName in the DEVMODE > structure and so you need to make sure that your code takes account of such > a possibility. As they say in all the best TV cookery programs, here's > something I prepared earlier (see below) ;-) > > Printing is still an evolving thing of course, and so if this code does not > work for your specific printer then perhaps you might like to consider my > other suggestion (asking the printer dialog to return a DC for you and > printing to that DC using API printing methods, which will definitely work > as long as your printer driver is installed properly). If you have any > problems then post again, although I imagine that the following code will > probably do the trick for you (paste it into a VB Form): > > Mike > > Option Explicit > 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 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 PD_PRINTSETUP =&H40 > 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 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 * 200 > 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 > dmICMMethod As Long > dmICMIntent As Long > dmMediaType As Long > dmDitherType As Long > dmReserved1 As Long > dmReserved2 As Long > dmPanningWidth As Long > dmPanningHeight As Long > End Type > > 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 SelectPrinter(frmOwner As Form, Optional _ > InitialPrinter As String, Optional _ > PrintFlags As Long = PD_PRINTSETUP) _ > As Boolean > Dim LongPrinterName As String > 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 p1 As Printer, NewPrinterName As String > PrintDlg.lStructSize = Len(PrintDlg) > PrintDlg.hwndOwner = frmOwner.hWnd > PrintDlg.flags = PrintFlags > On Error Resume Next > OriginalPrinter = Printer.DeviceName > If Len(InitialPrinter)> 0 Then > For Each p1 In Printers > If InStr(1, p1.DeviceName, InitialPrinter, _ > vbTextCompare)> 0 Then > Set Printer = p1 > Exit For > End If > Next > End If > DevMode.dmDeviceName = Printer.DeviceName > DevMode.dmSize = Len(DevMode) > DevMode.dmFields = DM_ORIENTATION > DevMode.dmPaperWidth = Printer.Width > DevMode.dmOrientation = Printer.Orientation > DevMode.dmPaperSize = Printer.PaperSize > 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 > CopyMemory DevName, ByVal lpDevName, Len(DevName) > LongPrinterName = Mid$(DevName.extra, _ > DevName.wDeviceOffset - DevName.wDriverOffset + 1) > LongPrinterName = Left$(LongPrinterName, _ > InStr(LongPrinterName, Chr$(0)) - 1) > DoEvents ' allow dialog to remove itself from display > Me.Refresh > SelectPrinter = 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 Printer.DeviceName<> _ > LongPrinterName Then > For Each p1 In Printers > If p1.DeviceName = _ > LongPrinterName Then > Set Printer = p1 > End If > Next > End If > On Error Resume Next > ' Transfer settings from the Devmode structure to the > ' VB printer object (this example just transfers some > ' of them but you can of course use transfer more) > 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 > SetBkMode Printer.hdc, TRANSPARENT > ' > On Error GoTo 0 > Else > SelectPrinter = False ' user cancelled > For Each p1 In Printers > If p1.DeviceName = OriginalPrinter Then > Set Printer = p1 > Exit For > End If > Next > GlobalFree PrintDlg.hDevNames > GlobalFree PrintDlg.hDevMode > End If > End Function > > Private Sub Command1_Click() > ' Note: Specifying Printer.DeviceName in the following > ' line will start the dialog off with the default > ' printer initially selected in the selection box, but > ' you can use any other string you wish. For example, > ' using "Epson" will cause the dialog to start with > ' the first printer it finds with the word "Epson" > ' in its device name. > If SelectPrinter(Me, Printer.DeviceName) Then > Printer.TrackDefault = False > Printer.ScaleMode = vbInches > ' set origin to top left corner of physical page > ' (otherwise it would be the top left corner of > ' the printable area, which is not the same) > SetPrinterOrigin 0, 0 > Printer.CurrentX = 1: Printer.CurrentY = 1 > Printer.Print "Hello World" > Printer.EndDoc > End If > End Sub > > > > > > > > > > > >
From: M Wade on 16 Jun 2010 13:55 Mike,I much appreciate you response and that from Shotgun Thom. My use of VB6 is almost totally for my own use and some I have developed for churches and a privately owned travel agency, so I am not a professional programmer. The specific program I am working on now is to catalog books and being able to search by author's name,Book Series and Book Title. If I print all of the entries it could go quite a few pages, hence the desire to use the duplex capability of the printer which is a network device. I can easily change the printer setting before running the program and reset it after the printing is done but I am interested enough to want to try something within the program. At age 77 and long retired I have the time to do that (hopefully). I am not very clear on using APIs and haven't the foggiest idea what the reference to DC is, but I am going to see if I can understand the code you supplied. Thanks again. Marv On 6/16/2010 12:52 PM, Mike Williams wrote: > "M Wade"<nowhere(a)columbus.rr.com> wrote in message > news:us2krNNDLHA.3492(a)TK2MSFTNGP02.phx.gbl... > >> I have an application that printed multiple pages and >> I have a printer (BROTHER 5370DW) that allows this. >> I select the printer using the CommonDialog1.ShowPrinter >> command and then click on the printer preferences to select >> two-sided printing. However, when the actual printing >> takes place is does not print two-sided. Is there something >> in VB print methods that would over-ride this option or not allow it? > > Under normal usage (from WinXP onwards) the CommonDialog Control changes > only the printer to be used and not any of its properties (although the user > can on most systems manually edit the properties in the dialog by right > clicking as suggested by Shotgun Thom, but in that case you need to > specifically advise your user to do something that he would not normally do > and those edits would "stick" beyond your own application and become the > default properties for all applications unless you asked your user to > specifically negate them afterwards, and for both of those reasons it is not > something I would advise). > > If you want to change the VB Printer Object's properties to those selected > by the user in the CommonDialog then you need to transfer them from the > CommonDialog properties to the equivalent VB Printer Object properties. > However, the CommonDialog Control does not have a Duplex property and so you > cannot do that in this specific case. In any case, I would personally advise > against using the CommonDialog in the normal way anyway, because when the > user selects a printer in it then that printer becomes the user's new system > default printer (unless you set the PrinterDefault property to False, which > in most cases defeats the object altogether). This is not how most > applications behave. The best way is to allow your user to select the > desired printer and for that printer to be used only for your own VB > application, without it altering the user's system default printer or any of > its default properties. > > Of all the available methods (of which there are many) the one I would > advise you to use is to display a printer dialog (using either the > CommonDialog Control or the equivalent API dialog) and ask it to return a DC > for you. Your VB application can then print to that returned DC safe in the > knowledge that the printer will be set up /exactly/ as the user has selected > in the printer dialog, including all of the sometimes rather esoteric > settings that certain specialist printers have and that are simply not > accessible by any other means (for example, the "use metallic gold ribbon" > setting on a Citizen Printiva printer, which is something that Windows > itself knows nothing about). That is by far the best method, and it is > essentially the method used by most professional applications. The problem > with this method of course is that you cannot effectively use it with the VB > Printer Object and so you will need to perform all your printing output > using the equivalent API printing methods. It is however what I would > advise. > > If you woud prefer to stick with the VB Printer Object then there are other > methods you can use to display a dialog that returns more information for > you than does the CommonDialog Control, and that avoids the "printer > settings sticks as the default" problem and allows your use to select from > most of the common properties, including your own desired duplex printing > option. Your code can then transfer those settings to the VB printer Object > for printing. > > There is a Micro$oft DLL that can help you to do this (from memory I think > it is called msvbprndlg.dll or something similar) but you can do the same > sort of thing without needing to package a DLL by using standard API dialog > calls, although you need to take account of the fact that some printers > (probably mostly network printers) have a device name that is longer than > the standard maximum 32 character length for dmDeviceName in the DEVMODE > structure and so you need to make sure that your code takes account of such > a possibility. As they say in all the best TV cookery programs, here's > something I prepared earlier (see below) ;-) > > Printing is still an evolving thing of course, and so if this code does not > work for your specific printer then perhaps you might like to consider my > other suggestion (asking the printer dialog to return a DC for you and > printing to that DC using API printing methods, which will definitely work > as long as your printer driver is installed properly). If you have any > problems then post again, although I imagine that the following code will > probably do the trick for you (paste it into a VB Form): > > Mike > > Option Explicit > 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 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 PD_PRINTSETUP =&H40 > 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 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 * 200 > 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 > dmICMMethod As Long > dmICMIntent As Long > dmMediaType As Long > dmDitherType As Long > dmReserved1 As Long > dmReserved2 As Long > dmPanningWidth As Long > dmPanningHeight As Long > End Type > > 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 SelectPrinter(frmOwner As Form, Optional _ > InitialPrinter As String, Optional _ > PrintFlags As Long = PD_PRINTSETUP) _ > As Boolean > Dim LongPrinterName As String > 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 p1 As Printer, NewPrinterName As String > PrintDlg.lStructSize = Len(PrintDlg) > PrintDlg.hwndOwner = frmOwner.hWnd > PrintDlg.flags = PrintFlags > On Error Resume Next > OriginalPrinter = Printer.DeviceName > If Len(InitialPrinter)> 0 Then > For Each p1 In Printers > If InStr(1, p1.DeviceName, InitialPrinter, _ > vbTextCompare)> 0 Then > Set Printer = p1 > Exit For > End If > Next > End If > DevMode.dmDeviceName = Printer.DeviceName > DevMode.dmSize = Len(DevMode) > DevMode.dmFields = DM_ORIENTATION > DevMode.dmPaperWidth = Printer.Width > DevMode.dmOrientation = Printer.Orientation > DevMode.dmPaperSize = Printer.PaperSize > 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 > CopyMemory DevName, ByVal lpDevName, Len(DevName) > LongPrinterName = Mid$(DevName.extra, _ > DevName.wDeviceOffset - DevName.wDriverOffset + 1) > LongPrinterName = Left$(LongPrinterName, _ > InStr(LongPrinterName, Chr$(0)) - 1) > DoEvents ' allow dialog to remove itself from display > Me.Refresh > SelectPrinter = 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 Printer.DeviceName<> _ > LongPrinterName Then > For Each p1 In Printers > If p1.DeviceName = _ > LongPrinterName Then > Set Printer = p1 > End If > Next > End If > On Error Resume Next > ' Transfer settings from the Devmode structure to the > ' VB printer object (this example just transfers some > ' of them but you can of course use transfer more) > 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 > SetBkMode Printer.hdc, TRANSPARENT > ' > On Error GoTo 0 > Else > SelectPrinter = False ' user cancelled > For Each p1 In Printers > If p1.DeviceName = OriginalPrinter Then > Set Printer = p1 > Exit For > End If > Next > GlobalFree PrintDlg.hDevNames > GlobalFree PrintDlg.hDevMode > End If > End Function > > Private Sub Command1_Click() > ' Note: Specifying Printer.DeviceName in the following > ' line will start the dialog off with the default > ' printer initially selected in the selection box, but > ' you can use any other string you wish. For example, > ' using "Epson" will cause the dialog to start with > ' the first printer it finds with the word "Epson" > ' in its device name. > If SelectPrinter(Me, Printer.DeviceName) Then > Printer.TrackDefault = False > Printer.ScaleMode = vbInches > ' set origin to top left corner of physical page > ' (otherwise it would be the top left corner of > ' the printable area, which is not the same) > SetPrinterOrigin 0, 0 > Printer.CurrentX = 1: Printer.CurrentY = 1 > Printer.Print "Hello World" > Printer.EndDoc > End If > End Sub > > > > > > > > > > > >
|
Next
|
Last
Pages: 1 2 3 Prev: Windows 7 Compliance: VB6 and Adhering to REstart Manager messages Next: Poooooor Fred... |