ResetDC() ничего не делает (печатает API диспетчера очереди печати для Windows)

Я написал классы-оболочки для API диспетчера очереди печати Windows, которые работают... в основном.

Единственное, что не работает - это применение настроек принтера.

Сначала я вызываю DocumentProperties(), чтобы успешно получить и поиграть с настройками принтера.

Затем я пытаюсь применить эти настройки с помощью ResetDC(), но ничего не происходит. Функция принимает действительный дескриптор и возвращает тот же действительный дескриптор, что означает, что она должна была применить настройки. Но, похоже, ничего не произошло: на распечатки не влияют изменения настроек принтера.

Я даже пытался использовать SetPrinter() с уровнем 9, также безрезультатно.

Эта задача становится довольно актуальной. Какие-либо предложения?

Использование Delphi XE2, Windows 7 64-bit.


Хорошо, пропустите всю большую часть больших 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;

0 ответов

Другие вопросы по тегам