Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Wanet Telecoms Ltd on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Modify Printer Settings with DocumentProperties?

Status
Not open for further replies.

RMS001

Programmer
Nov 12, 2002
45
CA
Hi
There are examples of this in MSDN written in C, by getting, then modifying and then rewriting the DEVMODE structure.
Can anyone help me translate it to Visual Basic?
Appleman has an example which I can follow until he calls a routine in his APIGID32.DLL for memory manipulation and loses me.

As much as I would like to know how to do this - to be able to change the PrintQuality setting - I'm not sure if it will solve my Visual Basic Application problem!

It seems that when I bring up the ShowPrint dialog and modify the Quality setting in the Properties dialog to a higher value (e.g. from 360 to 720) it doen't take effect.
WHY, WHY, WHY...
My quest has led me to the DEVMODE structure but it seems to me the Printer Dialog changes should take effect if it is done just before printing.

This code will not use the new setting from the dialog:

CommonDialog1.PrinterDefault = True
CommonDialog1.CancelError = True
CommonDialog1.Flags = cdlPDPrintSetup
On Error Resume Next
CommonDialog1.ShowPrinter
If Err Then Exit Sub
' open the dialog, select Properties, change the
' Quality Setting and click OK
Printer.PaintPicture Picture1.Image, 300, 300
Printer.EndDoc

The output is still 360dpi.

My ability to understand this by researching the problem has turned up nothing. Either Visual Basic cannot use a different printer resolution than 360dpi or I have missed something in my dozen VB books and the VB documentation.
Any help would be very much appreciated - Thanx
 

Have you seen my reply in thread222-745750?

Have you checked the Printer.PrintQuality Setting before and after you call the common dialog to see if there is any change?

Are you changing the scalemode property to vbPixels?

Also, now about the devmode structure. I heard one of my old bosses say that certain elements of the devmode structures cannot be changed by VB. I have never read this or found any documentation upon the subject (never found one either), but you may want to check/search MS for the structure you are trying to modify and see if they have an example for VB.

Good Luck

 
Hi vb5prgrmr

Twips, unlike the pixel, express an absolute value for printing purposes(1/20 of a point). They are more precise and allow the printer driver to create smoother print operations (dpi does not mean pixels per inch).

I always change the scalemode to pixels in my projects because I use the API so much. But I thought in this case, twips would allow the finer resolution to take effect.

In my testing, I do check the Printer.PrintQuality setting before and after the dialog box. It doesn't change - and that is the reason I am stumped.

Appleman has a demo that changes the DEVMODE structure and then prints a graphic. The value returned by his program seems to indicate that the dmPrintQuality has been changed through code - but the graphic, and the photo that I replaced his graphic with, still print at the lower resolution.

I am starting to think that VB is only capable of printing at the lower resolution, but if someone has seen otherwise I would like to know.

MSDN has an example of changing the Duplex property as a VBA modification in Word using the DEVMODE structure, but my observations so far are that Visual Basic is not recognizing the changes.

Thanks for responding to the post, you have some good obsevations and if you have a chance, try the code (it's pretty short) and see if you get the same results.

[and Confucius said, "Whaaaat?..."]
 

Uummmm ... I know that DPI does not stand for pixels but for dots. Although did you read the other thread where I posted the info from the help files?

I am wondering a couple of things that you may want to give a try.

Prior to calling the showprinter method read and change the printquality and see if it takes (all before the showprinter method).

I am wondering if you have to use (with your current printer/driver and vb) -4 to get it to print at a high quality?

Also there is some code in this thread222-693606 that may help. It does not currently do what you want it to do but look for the last function in the big post of mine. It may give some insite and I think you could change it to meet your needs.

Good Luck

 
Yes your code was helpful - I plugged it in and now know that the orientation property can be changed by code.

***Still can't change*** the PrintQuality thru code, (using -4 or a value of 720) and can't change the Orientation or the PrintQuality through the dialog box.

The dialog box works fine with any other application: Word, PaintShopPro, Paint, Adobe Reader; all other apps can change the printer dpi in the dialog box why not my Visual Basic app???


Maybe someone has the key - Please help!
 
You can use one of the device independent constants (-1 to -4) which may or may not be supported by the printer driver.

Alternatively, you can set the dmPaperQuality member to a positive value in dpi. If you do this it represents the X resolution and the dmYResolution member must also be set to a value in dpi.

I normally check to see if the printer supports the proposed new setting:
Code:
Case DM_YRESOLUTION
 If Not pudtDM.dmYResolution = intNewValue Then
  'If the new setting differs from the existing one
  'Check the printer supports this setting
  If Not CBool(pudtDM.dmFields And DM_YRESOLUTION) Then
   'Return a failure code in lngError
   lngError = PDXErrors.pdxerrDeviceNotCapable
   fChangePrinterSetting = False
   GoTo ExitFunc
  End If
 'Change the setting in the DEVMODE
  pudtDM.dmYResolution = intNewValue
 End If

Paul Bent
Northwind IT Systems
 
Hi Paul - Thanks for posting (I checked out your web-site. Some nice things you're doing).

I have two code samples that get and alter the DEVMODE structure.
They open the Print Dialog box, allow you to make changes, (the PrintQuality is the one I'm trying to set), and place the new info into the DEVMODE out structure.
While the structure reflects the changes, the Print.PrintQuality property in my program does not change.
Every app on my system that prints can modify the PrintQuality (Best - Normal - Draft) in the print dialog and then print in the chosen resolution (720 or 360 or 180).
I even have a sample in C++ (Petzold's "POPPAD") that changes the value in a dialog box and then prints in the selected resolution. Unfortunately, I don't understand the C code and can't translate it to VB6.
Why can all these programs change the PrintQuality property and it is not changeable in VB?
I tried adding ResetDC after the devmode is changed but still no luck.
Here is the code.
(If any one can tell me how to do this I would appreciate it. There is no need to check if the driver supports this setting. Obviously it does or the other apps that change the setting would not be able to do so). Also when I change the 'default' setting in the printer properties, the new value is reflected in the Print.PrintQuality property in VB.


CODE SAMPLE 1:

Public Sub ShowPrinter(frmOwner As Form, Optional PrintFlags As Long)
Dim PRINTDLG As PRINTDLG_TYPE
Dim DevModePrn As DEVMODE
Dim DevName As DEVNAMES_TYPE

Dim lpDevMode As Long, lpDevName As Long
Dim bReturn As Integer
Dim objPrinter As Printer, NewPrinterName As String

' Use PrintDialog to get the handle to a memory
' block with a DevMode and DevName structures

PRINTDLG.lStructSize = Len(PRINTDLG)
PRINTDLG.hwndOwner = frmOwner.hwnd

PRINTDLG.flags = PrintFlags
On Error Resume Next
'Set the current orientation and duplex setting
DevModePrn.dmDeviceName = Printer.DeviceName
DevModePrn.dmSize = Len(DevModePrn)
DevModePrn.dmFields = DM_ORIENTATION Or DM_DUPLEX
DevModePrn.dmPaperWidth = Printer.Width
DevModePrn.dmOrientation = Printer.Orientation
DevModePrn.dmPaperSize = Printer.PaperSize
DevModePrn.dmDuplex = Printer.Duplex
On Error GoTo 0

'Allocate memory for the initialization hDevMode structure
'and copy the settings gathered above into this memory
PRINTDLG.hDevMode = GlobalAlloc(GMEM_MOVEABLE Or GMEM_ZEROINIT, Len(DevModePrn))
lpDevMode = GlobalLock(PRINTDLG.hDevMode)
If lpDevMode > 0 Then
CopyMemory ByVal lpDevMode, DevModePrn, Len(DevModePrn)
bReturn = GlobalUnlock(PRINTDLG.hDevMode)
End If

'Set the current driver, device, and port name strings
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

'Allocate memory for the initial hDevName structure
'and copy the settings gathered above into this memory
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

'Call the print dialog up and let the user make changes
If PrintDialog(PRINTDLG) <> 0 Then

'First get the DevName structure.
lpDevName = GlobalLock(PRINTDLG.hDevNames)
CopyMemory DevName, ByVal lpDevName, 45
bReturn = GlobalUnlock(lpDevName)
GlobalFree PRINTDLG.hDevNames

'Next get the DevMode structure and set the printer
'properties appropriately
lpDevMode = GlobalLock(PRINTDLG.hDevMode)
CopyMemory DevModePrn, ByVal lpDevMode, Len(DevModePrn)
bReturn = GlobalUnlock(PRINTDLG.hDevMode)
GlobalFree PRINTDLG.hDevMode
NewPrinterName = UCase$(Left(DevModePrn.dmDeviceName, InStr(DevModePrn.dmDeviceName, Chr$(0)) - 1))
If Printer.DeviceName <> NewPrinterName Then
For Each objPrinter In Printers
If UCase$(objPrinter.DeviceName) = NewPrinterName Then
Set Printer = objPrinter
'set printer toolbar name at this point
End If
Next
End If

On Error Resume Next
'Set printer object properties according to selections made
'by user
ResetDC Printer.hdc, DevModePrn
Printer.Copies = DevModePrn.dmCopies
Printer.Duplex = DevModePrn.dmDuplex
Printer.Orientation = DevModePrn.dmOrientation
Printer.PaperSize = DevModePrn.dmPaperSize
'***THE NEXT LINE DOES NOT TAKE EFFECT!***
Printer.PrintQuality = DevModePrn.dmPrintQuality
Printer.ColorMode = DevModePrn.dmColor
Printer.PaperBin = DevModePrn.dmDefaultSource
On Error GoTo 0
End If
End Sub


CODE SAMPLE 2: Fron Dan Appleman - Uses his APIGID32.DLL (agFunctionName calls)

Private Sub mnuDocProperties_Click()
Dim dm As DEVMODE, dmout As DEVMODE
Dim bufsize&, res&
Dim dmInBuf() As Byte
Dim dmOutBuf() As Byte
Dim hPrinter&
Dim DeviceName$

hPrinter = OpenDefaultPrinter(DeviceName$)
If hPrinter = 0 Then
MsgBox &quot;Unable to open default printer&quot;
Exit Sub
End If

' The output DEVMODE structure will reflect any changes
' made by the printer setup dialog box.
' Note that no changes will be made to the default
' printer settings!
bufsize = DocumentProperties(hwnd, hPrinter, DeviceName$, 0, 0, 0)
ReDim dmInBuf(bufsize)
ReDim dmOutBuf(bufsize)

res = DocumentProperties(hwnd, hPrinter, DeviceName$, agGetAddressForObject(dmOutBuf(0)), agGetAddressForObject(dmInBuf(0)), DM_IN_PROMPT Or DM_OUT_BUFFER)

' Copy the data buffer into the DEVMODE structure
agCopyData dmOutBuf(0), dmout, Len(dmout)
ClosePrinter hPrinter
End Sub
 
If you send me an e-mail via the contact page on my web site, I can send you a sample VB project that demos the print dialog. I got it from MS Business Languages Support a couple of years ago. You may be able to get it to work with print quality.

Out of curiosity, have you tried using my ActiveX DLL, PDXPro, to change the print quality from your app? It doesn't display the Print dialog but can change the setting directly. I'm curious to know if your app will then print to the new setting.

Paul Bent
Northwind IT Systems
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top