2009. április 8., szerda

How to change the print orientation after BeginDoc and before EndDoc


Problem/Question/Abstract:

I want to change the print orientation and use printer.newpage to make just one job to print several pages.

Answer:

procedure TForm1.Button2Click(Sender: TObject);
var
  Device: array[0..255] of char;
  Driver: array[0..255] of char;
  Port: array[0..255] of char;
  hDeviceMode: THandle;
  pDevMode: PDeviceMode;
begin
  with Printer do
  begin
    BeginDoc;
    try
      Canvas.font.size := 20;
      Canvas.font.name := 'Arial';
      Canvas.TextOut(50, 50, 'This is portrait');
      GetPrinter(Device, Driver, Port, hDeviceMode);
      pDevMode := GlobalLock(hDevicemode);
      with pDevMode^ do
      begin
        dmFields := dmFields or DM_ORIENTATION;
        dmOrientation := DMORIENT_LANDSCAPE;
      end;
      {Cannot use NewPage here since the ResetDc will only work between
                        EndPage and StartPage.
      As a consequence the Printer.PageCount is not updated.}
      Windows.EndPage(Printer.Handle);
      if ResetDC(canvas.Handle, pDevMode^) = 0 then
        ShowMessage('ResetDC failed, ' + SysErrorMessage(GetLastError));
      GlobalUnlock(hDeviceMode);
      Windows.StartPage(Printer.Handle);
      Printer.Canvas.Refresh;
      Canvas.font.size := 20;
      Canvas.font.name := 'Arial';
      Canvas.TextOut(50, 50, 'This is landscape');
    finally
      EndDoc;
    end;
  end;
end;

The orientation change requires a call to the API function ResetDC, and this function only succeeds if it is called after EndPage and before StartPage. Since the TPrinter.NewPage method does both you cannot use it. The above works but the internal page count of the Printer object is not updated, you have to maintain your own if you need to display it in the printed pages.

Nincsenek megjegyzések:

Megjegyzés küldése