Printing to specific printer impossible?

It’s rare I’ve had to do printing, so I haven’t touched this concept in a very long while. But according to the docs, what I expect to be true, still should be. However… it doesn’t seem to be that way. From http://developer.xojo.com/userguide/printing

So I’ve done that.

Dim Setup As New PrinterSetup Setup.SetupString = DecodeBase64(Preferences.PrinterSetup) If Setup.PageSetupDialog(Self) Then Preferences.PrinterSetup = EncodeBase64(Setup.SetupString) End If

Well, this doesn’t work. The dialog has no option for selecting a printer, only options for selecting minimal formatting for the system’s printers. Then, as expected, OpenPrinter(Setup) prints to the system default printer.

If I had to guess, modern macOS versions have removed the concept of page setup entirely. Most of Apple’s apps don’t have it, so this call seems legacy and Xojo has not yet adapted.

Is there any solution besides changing the user’s default printer, or saving the image to disk and asking CUPS to print it directly?

You can use NSPrintInfoMBS class with SetupString functions:

http://www.monkeybreadsoftware.net/class-nsprintinfombs.shtml

For Windows the same works with WindowsDeviceModeMBS:

http://www.monkeybreadsoftware.net/class-windowsdevicemodembs.shtml

in both cases, you can convert from Xojo’s printer setup to my classes, set a new printer in the class and convert back.

I think you can switch printer with applescript calls. or even with a shell command ?

tell application "Print Center" set printerlist to name of printers set oldprinter to name of current printer set printerchoice to (choose from list printerlist with prompt ¬ "Which printer to be default?" default items oldprinter) set myprinter to printer (printerchoice as string) set current printer to myprinter end tell

and

lpstat -p to get the printers list

lpoptions -d printername to chnge to the needed printer

I would like to get the equivalents in windows, or even linux.

[quote=311082:@Thom McGrath]It’s rare I’ve had to do printing, so I haven’t touched this concept in a very long while. But according to the docs, what I expect to be true, still should be. However… it doesn’t seem to be that way. From http://developer.xojo.com/userguide/printing
[/quote]
Page Setup has never, as long as I’ve used Mac’s, been to select the specific printer.
Personally I’d file a bug report about that line in the User Guide as it doesn’t strike me as being right on macOS.
It let you pick things like orientation, scaling, paper size etc.
Even the apps I have that still support this mechanism (Word Excel etc) dot select a printer in the Page Setup dialog.
They DO have a “Format For” popup that lets you pick settings for a specific printer - but when you do finally print you could print to a different one.

As Jean-Yves notes its pretty easy to get the name of the curernt printer, switch to a different one as “default”, then switch things back

Windows
Get the list of printers wmic printer get name,default
Set Default wmic printer where name='printername' call setdefaultprinter

Linux SHOULD respond to the same lpstat etc that you can use on OS X

Yeah, I’ve got a number of unpleasant solutions. I really don’t like tampering with the user’s default printer for fear of not setting it back. But it’s what I’ve done.

OpenPrinterDialog doesn’t work on MacOS? From the Windows side, PageSetupDialog allowed the user to select a specific printer up through Win XP. From that point on, we had to modify the code to something along the lines of

if Setup.PageSetupDialog then
   g = OpenPrinterDialog(Setup)
   if g <> nil then
      Preferences.PrinterSetup = EncodeBase64(Setup.SetupString)
   end
end

[quote=311101:@Tim Hare]OpenPrinterDialog doesn’t work on MacOS? From the Windows side, PageSetupDialog allowed the user to select a specific printer up through Win XP. From that point on, we had to modify the code to something along the lines of

if Setup.PageSetupDialog then g = OpenPrinterDialog(Setup) if g <> nil then Preferences.PrinterSetup = EncodeBase64(Setup.SetupString) end end [/quote]
It doesn’t seem to. I tried using OpenPrinterDialog, and while it does allow printer selection, and seems to return a different setup string after, I couldn’t get it to respect the selected printer in subsequent calls. Besides, OpenPrinterDialog isn’t really what I want in this case, as it is for unattended printing. I’d have to have the user print a test page and save that string afterwards, which would work, but isn’t ideal either. Assuming OpenPrinter respects the previously selected printer from OpenPrinterDialog.

Resurrecting this old thread because I am having troubles with it on macOS 10.14:

[quote=311086:@Christian Schmitz]You can use NSPrintInfoMBS class with SetupString functions:
http://www.monkeybreadsoftware.net/class-nsprintinfombs.shtml [/quote]

I use the method below to change the printer setup, having defined a PDFPrinter as default printer and a Dymo label printer as secondary device. When I invoke this method, NSPrintInfo will always show me PDFPrinter as printer name, and when I re-invoke it a second time after saving a Dymo page format, PrinterSetup will show “any printer” and a nameless page format, but at least with the correct dimensions.
Do I have to address NSPrintInfo differently to save the printer name?

[code] Public Sub ChangePrinterSetup()
Dim settings As String = app.Preferences.StringValue(kPrinterSetup)
If settings <> “” Then settings = DecodeBase64MBS(settings)
Dim setup As New PrinterSetup

#If TargetMacOS
If settings <> “” Then
Dim nssetup As New NSPrintInfoMBS(settings)
setup.SetupString = nssetup.SetupString
End If
#ElseIf TargetWindows
If settings <> “” Then
setup.SetupString = settings
End If
#EndIf
If setup.PageSetupDialog Then
#If TargetMacOS
dim nssetup as new NSPrintInfoMBS
nssetup.SetupString = setup.SetupString
// NSSetup.Printername is still “PDFPrinter” while the rest including paper name is changed correctly!!!
settings = nssetup.data
app.Preferences.StringValue(kPrinterSetup) = EncodeBase64MBS(settings, 0, “”)
#ElseIf TargetWindows
app.Preferences.StringValue(kPrinterSetup) = EncodeBase64MBS(setup.SetupString, 0, “”)
#EndIf
End If
CheckPrinterSetup
End Sub[/code]

Huh, curious. I just came here for the same reason - finding that my previously working code doesn’t work any more on 10.14.

My goal is to invoke the Printer Setup dialogs once during setup, then store their config and then later activate one of these saved configs in order to print to a particular printer, then switch to another setup and print to the other printer (I’m printing labels to various printers in succession).

Only if I display the Printer Setup dialogs by calling OpenPrinterSetup() each time before printing, the configs get activated in 10.14. But if I only call OpenPrinter(), then the configs are not activated. This used to work in 10.13, though.

I also tried using NSPrintInfoMBS but could not get that to work, either. A working example project would be nice to have. I’ll go seek one now.

(Oh, jeez - why can’t this forum software show the year with the date? When I read that Ulrich wrote this on “Oct '19”, I thought it was just a week ago. Ah yes, the year is displayed in a different place. But when you see one date, there’s no reason to look for another place - you assume you already have all the information. Damn web designers)

There does not seem to have a preference about this. The only way to get the full date is to bring the pointer over the date or time to get get a tool tip, or click:

image

1 Like

Okay, I think I’ve figured it out. The MBS example “Printer Selection in Cocoa” shows how to choose the printer:

// Set the chosen printer:
dim i as Integer = ... // choose the printer's index
dim printerNames() as string = NSPrinterMBS.printerNames
dim printer as NSPrinterMBS = NSPrinterMBS.printerWithName (printerNames(i))
NSPrintInfoMBS.sharedPrintInfo.printer = printer

// And then simply print as usual:
dim ps as new PrinterSetup
dim g as Graphics = OpenPrinter(ps)
g.Draw...

The above code works if you have no special configs per printer.

If you have individually prepared PrinterSetups, then you need to set the printer in the setups each time, like this:

// Choose the printer:
dim i as Integer = ... // choose the printer's index
dim printerNames() as string = NSPrinterMBS.printerNames
dim chosenPrinter as NSPrinterMBS = NSPrinterMBS.printerWithName (printerNames(i))

// Update the printer setup to use the chosen printer:
dim setupString as String = ... // whereever you get this from
dim pi as new NSPrintInfoMBS
pi.SetupString = setupString
pi.printer = chosenPrinter

// Now print as usual:
dim ps as new PrinterSetup
ps.SetupString = pi.SetupString
dim g as Graphics = OpenPrinter(ps)
g.Draw...