本文介绍了如何使用 WinSpool API 设置纸张尺寸?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法使用 XPS API,因为该程序必须能够在 Windows XP 上打印.

我正在尝试使用 WinSpool 将纸张尺寸从 Letter 设置为 A4.

这是我的测试代码:

varH : 句柄;I : TBytes;信息:PPrinterInfo2;NeededSize : DWORD;开发模式:PDeviceMode;PD : TPrinterDefaults;开始PD.pDatatype := nil;PD.pDevMode := nil;PD.DesiredAccess := PRINTER_ACCESS_ADMINISTER;如果不是 OpenPrinter('Brother HL-5350DN series Printer', H, @PD) 然后开始引发 Exception.Create('OpenPrinter 错误:' + SysErrorMessage(GetLastError));结尾;尝试断言(不是 GetPrinter(H,2,nil,0,@NeededSize));SetLength(I, NeededSize);信息 := @I[0];如果不是 GetPrinter(H, 2, Info, NeededSize, @NeededSize) 然后开始引发 Exception.Create('GetPrinter 错误:' + SysErrorMessage(GetLastError));结尾;DevMode := Info.pDevMode;DevMode.dmFields := DevMode.dmFields 或 DM_PAPERSIZE;DevMode.dmPaperSize := DMPAPER_A4;Info.pSecurityDescriptor := nil;//根据 MSDN,如果我们不打算更改它,它必须被取消.如果不是 SetPrinter(H, 2, Info, 0) 然后开始引发 Exception.Create('SetPrinter 错误:' + SysErrorMessage(GetLastError));结尾;最后关闭打印机(H);结尾;TPrintDialog.Create(Self).Execute;//这只是为了我可以检查纸张大小结尾;

我有两个与访问权限相关的问题.

如果我将 PD.DesiredAccess 设置为 PRINTER_ACCESS_ADMINISTERGetPrinter 调用失败,我猜这是由于 UAC.

如果我将它设置为 PRINTER_ACCESS_USEGetPrinter 调用成功并且信息结构很好,但是对 SetPrinter 的调用失败.>

有趣的是,当我忽略 SetPrinter 的结果时,即使 SetPrinter 失败,打印对话框也会报告 A4 作为打印机尺寸.

我是否完全错误地将正确设置的 PDeviceMode 传递给 OpenPrinter 就足够了?(我实际上是在写完这个问题后才想到的:-)

关于 VCL 的另一个问题:

如果我使用 Printers 单元,我怎么知道作为参数传递给 TPrinter.GetPrinter 方法的缓冲区必须有多大?

背景:

系统为:Windows 7 Professional 64-Bit English with English locale.

我正在尝试在网络打印机 (Brother HL-5350DN) 上打印到 A4 纸.

我已将控制面板中的所有打印机设置设置为 A4 纸,但我正在编写的 Delphi 2009 程序仍然获取 US Letter 的纸张尺寸.

换句话说:Delphi 程序不遵守打印机假脱机程序的默认设置.

如果我先运行 TPrinterDialog 并从那里手动选择正确的纸张尺寸(在高级打印机设置中),一切都很好.

程序必须在没有任何 UI 的情况下运行,所以我必须以编程方式解决这个问题,或者最好程序应该只尊重默认的 Windows 打印机假脱机程序设置.

也许我错过了一些重要的设置?

解决方案

就像 David 所写的,我的具体问题是通过在 Windows 中设置正确的打印机首选项来解决的.

我仍然没有找到为我的应用程序设置本地打印属性的方法,但这不再是必要的.

就像 Sertac 写的那样,您可以使用 TPrinter.GetPrinterTPrinter.SetPrinter 读取和写入全局打印机首选项.(见问题的评论)

由于没有人提供 anwser 并且问题现已解决,我将其标记为社区 wiki.随时改进此答案.

I can't use the XPS API since the program has to be able to print on Windows XP.

I'm trying to set the paper size from Letter to A4 using WinSpool.

This is my test code:

var
  H          : THandle;
  I          : TBytes;
  Info       : PPrinterInfo2;
  NeededSize : DWORD;
  DevMode    : PDeviceMode;
  PD         : TPrinterDefaults;
begin
  PD.pDatatype     := nil;
  PD.pDevMode      := nil;
  PD.DesiredAccess := PRINTER_ACCESS_ADMINISTER;
  if not OpenPrinter('Brother HL-5350DN series Printer', H, @PD) then begin
    raise Exception.Create('OpenPrinter error: ' + SysErrorMessage(GetLastError));
  end;
  try
    Assert(not GetPrinter(H, 2, nil, 0, @NeededSize));
    SetLength(I, NeededSize);
    Info := @I[0];
    if not GetPrinter(H, 2, Info, NeededSize, @NeededSize) then begin
      raise Exception.Create('GetPrinter error: ' + SysErrorMessage(GetLastError));
    end;
    DevMode             := Info.pDevMode;
    DevMode.dmFields    := DevMode.dmFields or DM_PAPERSIZE;
    DevMode.dmPaperSize := DMPAPER_A4;
    Info.pSecurityDescriptor := nil; // According to MSDN it has to be niled if we're not going to change it.

    if not SetPrinter(H, 2, Info, 0) then begin
      raise Exception.Create('SetPrinter error: ' + SysErrorMessage(GetLastError));
    end;
  finally
    ClosePrinter(H);
  end;
  TPrintDialog.Create(Self).Execute; // This is just so I can check the paper size
end;

I have two problems related to access rights.

If I set PD.DesiredAccess to PRINTER_ACCESS_ADMINISTER the GetPrinter call fails, I guess this is due to UAC.

If I set it to PRINTER_ACCESS_USE the GetPrinter call succeeds and the Info structure is fine, but the call to SetPrinter fails.

Interestingly enough when I ignore the Result of SetPrinter the print dialog reports A4 as the printer size even though SetPrinter fails.

Am I doing it completly wrong and it is enough to pass a correctly setup up PDeviceMode to OpenPrinter? (I actually came up with this after writing this question :-)

Another question regarding the VCL:

If I use the Printers unit how do I know how big the buffers have to be that get passed as parameters to the TPrinter.GetPrinter method?

Background:

The system is: Windows 7 Professional 64-Bit English with English locale.

I'm trying to print to A4 paper on a network printer (Brother HL-5350DN).

I have set all printer settings in the control panel to A4 paper, but the Delphi 2009 program I'm writing still gets the paper dimensions for US Letter.

In other words: The Delphi program doesn't respect the default settings of the printer spooler.

If I run a TPrinterDialog first and select the correct paper size from there manually (in the advanced printer settings) everything is fine.

The program has to run without any UI, so I have to solve this programmatically or preferably the program should just respect the default Windows printer spooler settings.

Maybe I have missed some imporant setting?

解决方案

Like David wrote, my specific problem is solved by setting the correct printer preferences in Windows.

I still haven't found a way to set the local printing properties for my application, but that is no longer necessary.

Like Sertac wrote you can read and write the global printer preferences using TPrinter.GetPrinter and TPrinter.SetPrinter. (See the comments to the question)

Since nobody provided an anwser and the problem is now solved, I'm marking this as community wiki. Feel free to improve this answer.

这篇关于如何使用 WinSpool API 设置纸张尺寸?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-04 02:07
查看更多