-->

ResetDC()什么也不做(打印后台处理程序的API适用于Windows)(ResetDC() d

2019-10-16 15:38发布

我写的包装类Windows的后台打印程序的API ,其工作...居多。

工作的唯一的事情是将打印机设置

首先,我叫DocumentProperties()成功收购,并与打印机设置播放。

然后我尝试应用使用这些设置ResetDC(),但没有任何反应。 该功能需要一个有效的句柄,并返回相同的有效处理,这意味着它应该应用的设置。 但是,似乎没有任何已经发生:打印输出是由打印机设置的改变的影响。

我甚至试着使用SetPrinter()与9级 ,也没有效果。

这个任务越来越迫切相当。 有什么建议么?

用Delphi XE2,Windows 7的64位。


好吧,跳过所有的散装大OO包装的。 下面是一个浓缩的过程版本。 (请注意,你必须给它的XPS文件。)

打印机设置改变被应用 (使用Info2_Apply时()),并且可以在MS Word中看到。 他们打印时只是被忽略 。 这其中的奥秘。

我已经试过了我跑出来的选择这么多东西。 帮助会非常....大加赞赏。


我终于用完的选项。

下面是我的测试代码的最后版本。 这是自包含的,并包含更多的功能比你需要的 - 的拼命任何我能想到的结果。

如果任何人都可以得到打印机的设置工作,请你让我知道?

填充使用的打印机名称组合框:

uses
  Printers

ComboBox1.Items.Assign(Printer.Printers);

打印程序(我的测试代码):

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;

  //  Printer defaults

  procedure Defaults_Obtain(out DefaultsHandle: THandle; out Defaults: PPrinterDefaultsW);
  begin
    DefaultsHandle  := GlobalAlloc(GHND, SizeOf(TPrinterDefaultsW));
    if  DefaultsHandle = 0  then
      RaiseLastOSError;
    Defaults  := GlobalLock(DefaultsHandle);
    if  Defaults = nil  then
      RaiseLastOSError;
  end;

  //  Print settings

  procedure Settings_Obtain(Printer: THandle; out SettingsHandle: THandle; out Settings: PDeviceModeW);
  var
    DeviceModeSize: integer;
  begin
    DeviceModeSize  := DocumentProperties(0, Printer, PWideChar(PrinterName), nil, nil, 0);
    if  DeviceModeSize < 0 then
      RaiseLastOSError;
    //  Allocate memory
    SettingsHandle := GlobalAlloc(GHND, DeviceModeSize);
    if  SettingsHandle = 0 then
      RaiseLastOSError;
    //  Lock memory
    Settings := GlobalLock(SettingsHandle);
    if  Settings = nil then
      RaiseLastOSError;
    //  Populate memory
    if  DocumentProperties(ParentFormHandle, Printer, PWideChar(PrinterName), Settings, Settings, DM_OUT_BUFFER) < 0  then
      RaiseLastOSError;
  end;

  procedure Settings_Show(Printer: THandle; var Settings: PDeviceModeW; Options: Cardinal);
  var
    Return: integer;
  begin
    Return  := DocumentProperties(ParentFormHandle, Printer, PWideChar(PrinterName), Settings, Settings, Options);
    if  Return < 0  then
      RaiseLastOSError;
  end;

  //  DC

  function  ObtainDC(Printer: THandle; DeviceMode: PDeviceModeW): HDC;
  begin
    Result  := CreateDC(nil, PWideChar(PrinterName), nil, DeviceMode);
    if  Result = 0  then
      RaiseLastOSError;
  end;

  procedure ApplyDC(DC: HDC; DeviceMode: PDeviceModeW);
  begin
    if  ResetDC(DC, DeviceMode^) = 0  then
      RaiseLastOSError;
  end;

  //  PRINTER_INFO_2

  procedure Info2_Obtain(Printer: THandle; out Info2Handle: THandle; out Info2: PPrinterInfo2W);
  var
    InfoSize: Cardinal;
  begin
    GetPrinterW(Printer, 2, nil, 0, @InfoSize);
    //  Get printer info memory
    Info2Handle := GlobalAlloc(GHND, InfoSize);
    if  Info2Handle = 0 then
      RaiseLastOSError;
    //  Lock printer info memory
    Info2 := GlobalLock(Info2Handle);
    if  Info2 = nil then
      RaiseLastOSError;
    //  Get printer info data
    if  not GetPrinterW(Printer, 2, Info2, InfoSize, @InfoSize)  then
      RaiseLastOSError;
  end;

  procedure Info2_Apply(Printer: THandle; Info2: PPrinterInfo2W);
  begin
    if  not SetPrinterW(Printer, 2, Info2, 0) then
      RaiseLastOSError;
  end;

  //  PRINTER_INFO_8

  procedure Info8_Fetch(Printer: THandle; Settings: PDeviceModeW);
  var
    lBuffer: PPrinterInfo8W;
    lBufferSize: Cardinal;
  begin
    GetPrinterW(Printer, 8, nil, 0, @lBufferSize);
    GetMem(lBuffer, lBufferSize);
    try
      FillChar(lBuffer^, lBufferSize, 0);
      //  Make the call
      lBuffer.pDevMode  := Settings;
      if  not GetPrinterW(Printer, 8, lBuffer, lBufferSize, @lBufferSize) then
        RaiseLastOSError;
    finally
      FreeMem(lBuffer, lBufferSize);
    end;
  end;

  procedure Info8_Apply(Printer: THandle; Settings: PDeviceModeW);
  var
    lPrinterInfo8: TPrinterInfo8W;
  begin
    lPrinterInfo8.pDevMode  := Settings;
    if  not SetPrinterW(Printer, 8, @lPrinterInfo8, 0) then
      RaiseLastOSError;
  end;

  //  PRINTER_INFO_9

  procedure Info9_Fetch(Printer: THandle; Settings: PDeviceModeW);
  var
    lBuffer: PPrinterInfo9W;
    lBufferSize: Cardinal;
  begin
    GetPrinterW(Printer, 9, nil, 0, @lBufferSize);
    GetMem(lBuffer, lBufferSize);
    try
      FillChar(lBuffer^, lBufferSize, 0);
      //  Make the call
      lBuffer.pDevMode  := Settings;
      if  not GetPrinterW(Printer, 9, lBuffer, lBufferSize, @lBufferSize) then
        RaiseLastOSError;
    finally
      FreeMem(lBuffer, lBufferSize);
    end;
  end;

  procedure Info9_Apply(Printer: THandle; Settings: PDeviceModeW);
  var
    lPrinterInfo9: TPrinterInfo9W;
  begin
    lPrinterInfo9.pDevMode  := Settings;
    if  not SetPrinterW(Printer, 9, @lPrinterInfo9, 0) 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;

  //  General cleanup

  procedure ReleaseHandle(Handle: THandle);
  begin
    if  not GlobalUnlock(Handle)  then
      ;//RaiseLastOSError;
    if  GlobalFree(Handle) <> 0 then
      ;//RaiseLastOSError;
  end;

var
  PrinterA{, PrinterB}: THandle;
  Defaults: PPrinterDefaultsW;
  DefaultsHandle: THandle;
  DataType: string;
  Settings: PDeviceModeW;
  SettingsHandle: THandle;
  Info2: PPrinterInfo2W;
  Info2Handle: THandle;
//  DC: HDC;
  JobID: Cardinal;
begin
  if  not FileExists(FileNameXPS)  then
    raise Exception.Create('File not found: ' + FileNameXPS);

  //  Get DataType
  Printer_Open(PrinterA);
  try
    Info2_Obtain(PrinterA, Info2Handle, Info2);
    try
      DataType  := WideCharToString(Info2.pDatatype);
    finally
      ReleaseHandle(Info2Handle);
    end;
  finally
    Printer_Close(PrinterA);
  end;

  Defaults_Obtain(DefaultsHandle, Defaults);
  try
    Defaults.pDatatype      := PWideChar(DataType);
    Defaults.pDevMode       := nil;
    Defaults.DesiredAccess  := PRINTER_ALL_ACCESS;

    Printer_Open(PrinterA, Defaults);
    try
      Info2_Obtain(PrinterA, Info2Handle, Info2);
      try
        Settings_Show(PrinterA, Info2.pDevMode, DM_IN_BUFFER or DM_IN_PROMPT or DM_OUT_BUFFER);
        //  Try according to:
        //  - Remarks section in http://msdn.microsoft.com/en-us/library/windows/desktop/dd145082%28v=vs.85%29.aspx
        //  - Comment on code line 246 in http://www.lessanvaezi.com/changing-printer-settings-using-the-windows-api/
        Info2.pSecurityDescriptor := nil;
        Info2_Apply(PrinterA, Info2);

        JobID := JobCreate(PrinterA, FileNameXPS);
        JobStart(PrinterA, JobID);

      finally
        ReleaseHandle(Info2Handle);
      end;
    finally
      Printer_Close(PrinterA);
    end;
  finally
    ReleaseHandle(DefaultsHandle);
  end;

end;
文章来源: ResetDC() does nothing (print spooler API's for Windows)