3
votes

Using Windows Print Spooler API's, we can print out XPS files.

The problem is that the print spooler ignores the default printer settings.

(We've given up on trying to apply printer settings. Default printer settings will just have to suffice.)

For example... the printouts always come out in colour and on one paper per page, regardless of what the settings are set to in the control panel: black & white/colour, duplex/not duplex, multiple pages per sheet/single page per sheet.

Other applications such as MS Word and Adobe respect the default printer settings.

We're using Delphi XE2 and Windows 7 64-bit.

This test code is self contained, so you can just paste it in to test it...

Populate a combo box with printer names using:

uses
  Printers

ComboBox1.Items.Assign(Printer.Printers);

Printing procedure:

uses
  Winapi.WinSpool

procedure PrintXPS(PrinterName, FileNameXPS: string; ParentFormHandle: THandle = 0);

  //  Printer handle

  procedure Printer_Open(out Printer: THandle; Defaults: PPrinterDefaultsW = nil);
  begin
    if  not OpenPrinterW(PWideChar(PrinterName), Printer, Defaults) then
      RaiseLastOSError;
  end;

  procedure Printer_Close(Printer: THandle);
  begin
    if  not ClosePrinter(Printer) then
      RaiseLastOSError;
  end;

  //  Print jobs

  function  JobCreate(Printer: THandle; FileName: string): Cardinal;
  var
    lBufferSize: Cardinal;
    lAddJobInfo: PAddJobInfo1W;
  begin
    //  Create job
    AddJobW(Printer, 1, nil, 0, lBufferSize);
    GetMem(lAddJobInfo, lBufferSize);
    try
      if  not AddJobW(Printer, 1, lAddJobInfo, lBufferSize, lBufferSize)  then
        RaiseLastOSError;
      Result  := lAddJobInfo.JobId;
      //  Copy the file into place
      CopyFile(PWideChar(FileName), lAddJobInfo.Path, True);
    finally
      FreeMem(lAddJobInfo, lBufferSize);
    end;
  end;

  procedure JobStart(Printer: THandle; JobID: Cardinal);
  begin
    if  not ScheduleJob(Printer, JobID) then
      RaiseLastOSError;
  end;

var
  PrinterA: THandle;
  JobID: Cardinal;
begin
  if  not FileExists(FileNameXPS)  then
    raise Exception.Create('File not found: ' + FileNameXPS);

  Printer_Open(PrinterA, nil);
  try
    JobID := JobCreate(PrinterA, FileNameXPS);
    JobStart(PrinterA, JobID);
  finally
    Printer_Close(PrinterA);
  end;

end;
1
It's a while since I worked in this area, but if you are talking to the spooler direct, then the file you send it is the final printer ready content, and has nothing at all to do with the printer defaults. This is a good thing if you are spooling data files - consistency. If you want to print like Word etc, then you need to run the application with the print shell verb (which will be something like "%1 /Print").mj2008
That doesn't make sense to me. A user might want to use a different paper tray, or change the paper size, etc. regardless of how the XPS file was rendered to file.Peter Thönell
Thanks for the pointer about the shell commands. I'll investigate them.Peter Thönell

1 Answers

0
votes

Much as I know you can not change the appearance of a .xps file.

XPS stands for XML Paper Specification, it is virtually an "electronic paper", the document on screen and in print is exactly the way it was intended by the author. Anyone who has ever experienced, how the page layout of an Office document on a shared computer because of a different default printer has shifted, appreciate it.

EDIT

Test

1.) Default black and white printer settings. Open the. xps file Print.

  • With IE == colored output.
  • With XPS Viewer EP == colored output.

Default printer settings == ignored.

2.) Dialog: Printer-settings manually to print black and white set.

  • IE == black and white output.
  • XPS Viewer EP == black and white output.