Printer: How to get the device name
-
- Enthusiast
- Posts: 781
- Joined: Fri Apr 25, 2003 6:51 pm
- Location: NC, USA
- Contact:
Printer: How to get the device name
How can I retrieve the "device name" of the chosen printer after a
PrintRequester()
or
PrintDlg_().
I am lost trying to do this.
Terry
PrintRequester()
or
PrintDlg_().
I am lost trying to do this.
Terry
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
I added a couple lines to one of the functions from my xPrint library ( http://www.purebasic.fr/english/viewtopic.php?t=22409 ) that illustrates what you're looking for...
Note that the code is original based on code by Rings. Hope that helps!
Code: Select all
Procedure.l _xp_GetDefaultPrinterSettings(*HoldJob.s_xp_PrintJob)
; Fills the DEVMODE and PRINTDLG structures with information about the current default printer.
Define.DEVNAMES myDevNames
;
Define.l *HoldMode
;
Define.l lResult, ResultDLG
;
*HoldMode = AllocateMemory(SizeOf(DEVMODE))
;
If *HoldMode
;
*HoldJob\HoldDialog\lStructSize = SizeOf(PRINTDLG)
*HoldJob\HoldDialog\flags = #PD_RETURNDC | #PD_RETURNDEFAULT
*HoldJob\HoldDialog\hwndOwner = #Null
*HoldJob\HoldDialog\hDevMode = *HoldMode
*HoldJob\HoldDialog\hDevNames = #Null
*HoldJob\HoldDialog\hInstance = 0
*HoldJob\HoldDialog\lpfnSetupHook = #Null
*HoldJob\HoldDialog\lpPrintSetupTemplateName = #Null
*HoldJob\HoldDialog\lpPrintTemplateName = #Null
;
lResult = CopyMemory(@*HoldJob\HoldMode, *HoldMode, SizeOf(DEVMODE))
;
ResultDLG = PrintDlg_(*HoldJob\HoldDialog)
;
lResult = CopyMemory(*HoldMode, @*HoldJob\HoldMode, SizeOf(DEVMODE))
;/ The following block illustrates retrieving the printer name
Define.DEVMODE *HoldDev
*HoldDev = *HoldJob\HoldDialog\hDevMode
Debug PeekS(@*HoldDev\dmDeviceName[0])
;/
FreeMemory(*HoldMode)
;
EndIf
;
EndProcedure
Code: Select all
i.L
PrintDlg.PRINTDLG
PrinterName.S
Result.L
DevMode = GlobalAlloc_(#GMEM_MOVEABLE | #GMEM_ZEROINIT, SizeOf(DEVMODE))
DevModeLocked = GlobalLock_(DevMode)
PrintDlg\lStructSize = SizeOf(PRINTDLG)
PrintDlg\Flags = #PD_ALLPAGES
PrintDlg\hDevMode = DevModeLocked
Result = PrintDlg_(PrintDlg)
If Result <> #False
*DevMode.DEVMODE = PrintDlg\hDevMode
While i < 32 And PeekB(*DevMode + i) <> 0
PrinterName = PrinterName + Chr(PeekB(*DevMode + i))
i = i + 1
Wend
If Len(PrinterName) = 31
PrinterName = PrinterName + "..."
EndIf
MessageRequester("Printer Device Name", PrinterName, #MB_ICONINFORMATION)
EndIf
GlobalUnlock_(DevMode)
GlobalFree_(DevMode)
Xombie,
one small advice for your code example. If you are requesting a DC handle with #PD_RETURNDC you should delete it afterwards:
For further information take a look at the C example "Displaying the Print Dialog Box" in the MSDN:
http://windowssdk.msdn.microsoft.com/en ... 46829.aspx
one small advice for your code example. If you are requesting a DC handle with #PD_RETURNDC you should delete it afterwards:
Code: Select all
If lResult <> 0
DeleteDC_(*HoldJob\HoldDialog\hDC)
End If
http://windowssdk.msdn.microsoft.com/en ... 46829.aspx
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
Edwin,
you are right that ist is probably safer to read the device name from the DEVNAMES control structure. The MSDN says:
But because the call of the PrintDlg() function initializes the dialog box with the printer from wDeviceOffset it should be nearly as safe to use my code after the call of this function.
The possible truncation of the device name is already taken care of in my code and was successfully tested with a very long "friendly" printer name.
Nevertheless here is the "safer" solution which doesn't truncate the "friendly" printer name:
you are right that ist is probably safer to read the device name from the DEVNAMES control structure. The MSDN says:
http://windowssdk.msdn.microsoft.com/en ... 46843.aspxNote that the dmDeviceName member of the DEVMODE structure also specifies a printer name. However, dmDeviceName is limited to 32 characters, and the wDeviceOffset name is not. If the wDeviceOffset and dmDeviceName names are not the same, PrintDlg initializes the dialog box using the printer specified by wDeviceOffset.
But because the call of the PrintDlg() function initializes the dialog box with the printer from wDeviceOffset it should be nearly as safe to use my code after the call of this function.
The possible truncation of the device name is already taken care of in my code and was successfully tested with a very long "friendly" printer name.
Nevertheless here is the "safer" solution which doesn't truncate the "friendly" printer name:
Code: Select all
PrintDlg.PRINTDLG
DevNames = GlobalAlloc_(#GMEM_MOVEABLE | #GMEM_ZEROINIT, SizeOf(DEVNAMES))
DevModeLocked = GlobalLock_(DevNames)
PrintDlg\hDevMode = 0
PrintDlg\hDevNames = DevModeLocked
PrintDlg\lStructSize = SizeOf(PRINTDLG)
PrintDlg\Flags = #PD_ALLPAGES
If PrintDlg_(PrintDlg) <> #False
*DEVNAMES.DEVNAMES = PrintDlg\hDevNames
MessageRequester("Printer Device Name", PeekS(*DEVNAMES + *DEVNAMES\wDeviceOffset), #MB_ICONINFORMATION)
EndIf
GlobalUnlock_(DevNames)
GlobalFree_(DevNames)
Last edited by Shardik on Wed Aug 09, 2006 12:48 pm, edited 1 time in total.
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
1)
You should not pass a locked global mem but it's unlocked handle.
Somehow it sees it's already locked but it's not what it should expect.
2)
The first time you have succesful printdlg call(+OK) the devmode+devnames structures *are* created for you.
You better continue using those throughout the program.
No need to prepare a memory block yourself.
You should not pass a locked global mem but it's unlocked handle.
Somehow it sees it's already locked but it's not what it should expect.
2)
The first time you have succesful printdlg call(+OK) the devmode+devnames structures *are* created for you.
You better continue using those throughout the program.
No need to prepare a memory block yourself.
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
-
- Enthusiast
- Posts: 781
- Joined: Fri Apr 25, 2003 6:51 pm
- Location: NC, USA
- Contact:
Thanks for all the responses, guys.
However, I still don't have a valid "friendly" printer name being returned.
Shardik's latest code returns a "Q" which certainly isn't the name.
So far, I haven't been able to utilize Xombie's code and get any response. Probably something I did, but I just get a memory error with it.
No wonder I was confused. This seems terribly difficult.
However, I still don't have a valid "friendly" printer name being returned.
Shardik's latest code returns a "Q" which certainly isn't the name.
So far, I haven't been able to utilize Xombie's code and get any response. Probably something I did, but I just get a memory error with it.
No wonder I was confused. This seems terribly difficult.
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
I rewrote it and shows the printername:
Of course it lacks testing for valid memory and such..
Code: Select all
PrintDlg.PRINTDLG
PrintDlg\hDevMode = 0
PrintDlg\hDevNames = 0
PrintDlg\lStructSize = SizeOf(PRINTDLG)
PrintDlg\Flags = #PD_ALLPAGES
If PrintDlg_(PrintDlg) <> #FALSE
*DEVNAMES.DEVNAMES = GlobalLock_(PrintDlg\hDevNames)
MessageRequester("Printer Device Name", PeekS(*DEVNAMES + *DEVNAMES\wDeviceOffset), #MB_ICONINFORMATION)
GlobalUnlock_(PrintDlg\hDevNames)
EndIf
; Only at the end of the app
GlobalFree_(PrintDlg\hDevNames)
-
- Enthusiast
- Posts: 781
- Joined: Fri Apr 25, 2003 6:51 pm
- Location: NC, USA
- Contact:
Thanks, Edwin. That works for me here.Edwin Knoppert wrote:I rewrote it and shows the printername:
I got into this trying to print a page in landscape mode. Now, I can
at least try to get that working.
In fact, I have to also get the printer to select a second tray.
I will need all the help I can get.
Thanks to everyone who responded. It was all a big help.
Terry
-
- Addict
- Posts: 1073
- Joined: Fri Apr 25, 2003 11:13 pm
- Location: Netherlands
- Contact:
Terry,
I am sorry that my code didn't work for you. Did you test it with Win98? I had no problems running both examples under WinNT SP6 and WinXP SP2.
How do you want to switch to landscape mode? If you want to display the print dialog and preset to landscape mode, take a look at a code example from wichtel in the German forum:
http://www.purebasic.fr/german/archive/ ... php?t=1680
If you don't want to display the print dialog and change the landscape mode only for the default printer and the current print, take a look at this code example in the German forum:
http://www.purebasic.fr/german/archive/ ... c.php?t=83
If you want to change the default of a print dialog setting without displaying the print dialog, take a look at a code example from me in the German forum, which changes the number of copies to print for the default printer:
http://www.purebasic.fr/german/viewtopic.php?t=6453
Tell me, if you want to change the default setting to landscape mode (without displaying the print dialog) and I will post an adapted example for you.
Edwin,
thank you very much for optimizing my code and pinpointing its shortcuts. You are right that it is unnecessary to allocate memory and passing it to the print dialog if you only want to read from the DEVNAMES or DEVMODE structure. But the example was adapted from a code which manipulated the contents of the print dialog...
I am sorry that my code didn't work for you. Did you test it with Win98? I had no problems running both examples under WinNT SP6 and WinXP SP2.
How do you want to switch to landscape mode? If you want to display the print dialog and preset to landscape mode, take a look at a code example from wichtel in the German forum:
http://www.purebasic.fr/german/archive/ ... php?t=1680
If you don't want to display the print dialog and change the landscape mode only for the default printer and the current print, take a look at this code example in the German forum:
http://www.purebasic.fr/german/archive/ ... c.php?t=83
If you want to change the default of a print dialog setting without displaying the print dialog, take a look at a code example from me in the German forum, which changes the number of copies to print for the default printer:
http://www.purebasic.fr/german/viewtopic.php?t=6453
Tell me, if you want to change the default setting to landscape mode (without displaying the print dialog) and I will post an adapted example for you.
Edwin,
thank you very much for optimizing my code and pinpointing its shortcuts. You are right that it is unnecessary to allocate memory and passing it to the print dialog if you only want to read from the DEVNAMES or DEVMODE structure. But the example was adapted from a code which manipulated the contents of the print dialog...