印刷ジョブを分けずに用紙サイズを変更したい

解決


てつこ  2024-09-26 11:56:42  No: 151617  IP: [192.*.*.*]

こんにちは
ある複合機の機能を使用するために印刷ジョブを分けずに用紙サイズを変更する処理を作成しています
添付しているソースだと2ページ目でA3に変更しようとした時点で「現在印刷中です」というエラーが発生します
私自身「印刷中に用紙サイズの変更はできない」と認識しておりエラーも当然だと思っていましたが、
Word等のアプリケーションでは同一ジョブ内で異なる用紙サイズ出力を実現させています

印刷中に用紙サイズを変更する方法をご存じではないでしょうか
よろしくお願いします

uses
  Printers;

var
  Def_Port,
  Def_Device,
  Def_Driver     : array[0..250] of Char;
  Def_pDev       : PDevMode;
  Def_hDeviceMode: THandle;

procedure ChangePapersize(PaperName: String);
begin
  Printer.GetPrinter(Def_Device,Def_Driver,Def_Port,Def_hDeviceMode);
  Def_pDev:=GlobalLock(Def_hDeviceMode);
  if PaperName = 'A3' then Def_pDev^.dmPaperSize:=DmPaper_A3 else
  if PaperName = 'A4' then Def_pDev^.dmPaperSize:=DmPaper_A4;
  GlobalUnlock(Def_hDeviceMode);
  Printer.SetPrinter(Def_Device,Def_Driver,Def_Port,Def_hDeviceMode);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if PrintDialog1.execute then
    begin
      ChangePapersize('A4');
      Printer.BeginDoc;
      Printer.canvas.TextOut(100,100,PChar('PAGE1'));
      Printer.NewPage;
      ChangePapersize('A3');
      Printer.canvas.TextOut(100,100,PChar('PAGE2'));
      Printer.EndDoc;
    end;
end;

編集    削除
HFUKUSHI  2024-09-26 21:10:53  No: 151618  IP: [192.*.*.*]

TPrinter.NewPageの実装が
procedure TPrinter.NewPage;
begin
  CheckPrinting(True);
  EndPage(DC);
  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;
となっていて、NewPageを呼び出したら新しいページの処理が始まっちゃってるのが原因な気がします。
例えば
uses
  Vcl.Consts;

type
  TChangingPageProc = reference to procedure ();

  TPrinterHelper = class helper for TPrinter
  public
    procedure NewPage2(ChangingPageProc: TChangingPageProc);
  end;

procedure TPrinterHelper.NewPage2(ChangingPageProc: TChangingPageProc);
begin
  if Printing = False then
  begin
    raise EPrinter.Create(SNotPrinting);
  end;
  EndPage(Handle);
  if Assigned(ChangingPageProc) then
  begin
    ChangingPageProc();
  end;
  StartPage(Handle);
  Canvas.Refresh;
end;
こんなのを用意して、
      ChangePapersize('A4');
      Printer.BeginDoc;
      Printer.canvas.TextOut(100,100,PChar('PAGE1'));
      Printer.NewPage2(
        procedure
        begin
          ChangePapersize('A3');
        end);
      Printer.canvas.TextOut(100,100,PChar('PAGE2'));
      Printer.EndDoc;
こんな感じで用紙サイズを変更したらどうでしょう?
(動かして試していないのでダメだったらすいません

編集    削除
てつこ  2024-09-27 09:53:39  No: 151619  IP: [192.*.*.*]

HFUKUSHIさん ありがとうございます
Delphi11にて試してみましたが「現在印刷中です」というメッセージが表示され現象は変わらずでした

このメッセージはTPrinter.SetPrinter内の1行目CheckPrintingメソッドが発生させていました
TPrinter.SetPrinter内の全てを理解することはできませんがOpenPrinterやClosePrinterが行われていることから印刷実行中に使用するのは問題がありそうです

プリンタ設定を変更する方法としてTPrinter.SetPrinterに替る他の方法はあるのでしょうか
よろしくお願いします

編集    削除
AAAAA  2024-09-28 10:30:54  No: 151621  IP: [192.*.*.*]

わからんけど 

procedure ChangePapersize(PaperName: String);
begin
    Printer.GetPrinter(Def_Device,Def_Driver,Def_Port,Def_hDeviceMode);
    Def_pDev:=GlobalLock(Def_hDeviceMode);
    if PaperName = 'A3' then Def_pDev^.dmPaperSize:=DmPaper_A3 else
    if PaperName = 'A4' then Def_pDev^.dmPaperSize:=DmPaper_A4;
    GlobalUnlock(Def_hDeviceMode);
    ResetDC(Printer.Handle,Def_pDev^);
    //Printer.SetPrinter(Def_Device,Def_Driver,Def_Port,Def_hDeviceMode);
end;


procedure TForm1.Button1Click(Sender: TObject);
begin
    if PrintDialog1.execute then
    begin
      ChangePapersize('A4');
      Printer.BeginDoc;
      Printer.canvas.TextOut(100,100,PChar('PAGE1'));

      EndPage(Printer.Handle);
      ChangePapersize('A3');
      StartPage(Printer.Handle);

      Printer.canvas.TextOut(100,100,PChar('PAGE2'));
      Printer.EndDoc;
    end;
end;

編集    削除
てつこ  2024-09-30 11:15:22  No: 151622  IP: [192.*.*.*]

AAAAA さん

ResetDCを使用することで目的の処理を実現できました
大変助かりました

お返事いただいた皆さん、ありがとうございました

編集    削除