Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   TPrinter: Portrait auf Landscape umzuschalten (https://www.delphipraxis.net/201179-tprinter-portrait-auf-landscape-umzuschalten.html)

tomkupitz 29. Jun 2019 22:02

TPrinter: Portrait auf Landscape umzuschalten
 
Hallo,

gibt es eine Möglichkeit innerhalb eines Druckauftrages von Portrait auf Landscape umzuschalten?

Folgendes funktioniert nicht:

Delphi-Quellcode:
  Printer.Orientation:=poPortrait; //gilt für den gesamten Druckauftrag

  Printer.BeginDoc;

  Printer.Canvas.TextOut(100, 100, 'Seite 1');

  Printer.NewPage;

  Printer.Orientation:=poLandscape; //erwarteter Fehler

  Printer.Canvas.TextOut(100, 100, 'Seite 2');

  Printer.EndDoc;
Danke und beste Grüße

p80286 29. Jun 2019 22:25

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Nö das geht nicht:
Zitat:

Determines if the print job prints vertically or horizontally on a page.

Use Orientation to determine if a print job prints in landscape or portrait.
Du mußt für jede Orientation einen eigenen Printjob definieren, oder aber Du schickst die Druckersteuerdaten und die zu druckenden Daten direkt an den Drucker (falls das überhaupt noch geht?)

Gruß
K-H

einbeliebigername 30. Jun 2019 12:17

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Hallo,

Zitat:

Zitat von p80286 (Beitrag 1435631)
Nö das geht nicht:

Falsch. Es geht doch, ist bloß nicht so einfach.

Die Orientation bei einem Druckjob kann nur außerhalb einer Seite umgestellt werden.

Das Problem ist das NewPage:
Delphi-Quellcode:
procedure TPrinter.NewPage;
begin
  CheckPrinting(True);
  EndPage(DC);
  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;
Das Umschalten müsste zwischen
Delphi-Quellcode:
EndPage(DC);
und
Delphi-Quellcode:
StartPage(DC);
stattfinden. Meine Lösung war damals, den Sourcecode von TPrinter kopieren und das NewPage in EndPage und StartPage zerlegen.

einbeliebigername.

peterbelow 30. Jun 2019 12:27

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Zitat von tomkupitz (Beitrag 1435629)
Hallo,

gibt es eine Möglichkeit innerhalb eines Druckauftrages von Portrait auf Landscape umzuschalten?

Danke und beste Grüße

Ich habe folgendes in meiner alten Codesammlung gefunden:

Delphi-Quellcode:
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 portait');
      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;

tomkupitz 30. Jun 2019 17:23

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Ich habe mal Folgendes in Printers.pas eingebaut:

Delphi-Quellcode:
    procedure NewPage;
    procedure BeginNewPage;
    procedure EndNewPage;

...

[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.NewPage;
begin
  CheckPrinting(True);
  EndPage(DC);
  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;

[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.BeginNewPage;
begin
  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;

[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.EndNewPage;
begin
  CheckPrinting(True);
  EndPage(DC);
end;
Leider erhalte dabei die Fehlermeldung:

[dcc32 Fataler Fehler] Vcl.Printers.pas(1550): F2613 Unit 'Vcl.Dialogs' nicht gefunden.

zeras 30. Jun 2019 17:46

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Zitat von tomkupitz (Beitrag 1435687)
Leider erhalte dabei die Fehlermeldung:

[dcc32 Fataler Fehler] Vcl.Printers.pas(1550): F2613 Unit 'Vcl.Dialogs' nicht gefunden.

Dann binde doch die VCL.Dialogs unter uses mit ein.

tomkupitz 30. Jun 2019 18:04

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Dann binde doch die VCL.Dialogs unter uses mit ein.
1. Warum, bei diesen Änderungen?
2. Ich erhalte dann den Fehler: Zu wenig Arbeitsspeicher.

zeras 30. Jun 2019 18:13

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Zitat von tomkupitz (Beitrag 1435690)
1. Warum, bei diesen Änderungen?

Hast du vielleicht einen Öffnen/Speichern Dialog noch mit eingebaut?
Klicke doch auf die Fehlermeldung. Dann wirst du sehen, in welcher Zeile da etwas fehlt.

Zitat:

Zitat von tomkupitz (Beitrag 1435690)
2. Ich erhalte dann den Fehler: Zu wenig Arbeitsspeicher.

Dafür habe ich keine Erklärung, aber vielleicht reicht es, Delphi oder den Rechner neu zu starten.

tomkupitz 30. Jun 2019 18:45

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Hast du vielleicht einen Öffnen/Speichern Dialog noch mit eingebaut?
Nein, nur gezeigten Code.

Zitat:

Klicke doch auf die Fehlermeldung. Dann wirst du sehen, in welcher Zeile da etwas fehlt.
Fehlerzeile ist letzte Printers.pas Zeile -> end.

zeras 30. Jun 2019 19:10

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Wie ist DC deklariert?
Delphi-Quellcode:
EndPage(DC);

Schokohase 30. Jun 2019 19:49

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Das Problem ist ganz woanders ...

In der Vcl.Dialogs wird die Unit Vcl.Printers verwendet. Da aber jetzt das Interface der Unit Vcl.Printers verändert wurde (neue Methoden) kommt der Kompiler/Linker damit nicht mehr klar (weil die vorkompilierte Vcl.Dialogs verwendet wird) und produziert diesen seltsamen Fehler.

peterbelow 1. Jul 2019 10:04

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Zitat von tomkupitz (Beitrag 1435687)
Ich habe mal Folgendes in Printers.pas eingebaut:

Mach das nicht, es ist nie eine gute Idee, eine der Delphi source files direkt zu verändern. Das führt zu Problemen mit anderen RTL/VCL units, die dann eventuell auch neu kompiliert werden müssen, was dann nur geht, wenn Du die Verzeichnisse mit den Sourcefiles in den search path mit aufnimmst, was dann eine ganze Lawine von anderen Versionkonflikten nach sich ziehen kann.

Mach eine Kopie der vcl.printer.pas Datei und benenne die Unit um. Modifiziere diese Datei und verwende sie dann anstelle von vcl.printers in deinem Projekt.

tomkupitz 1. Jul 2019 10:25

AW: TPrinter: Portrait auf Landscape umzuschalten
 
vcl.printer.pas ist natürlich eine Kopie im lokalen Projektverzeichnis. Originale Units ändere ich nie.

Aber die Probleme mit der vcl.printer.pas-Kopie sind so einfach nicht lösbar.

Peter: Ich werde mir mal dein Beispiel ansehen.

Danke an alle und beste Grüße

einbeliebigername 1. Jul 2019 13:14

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Hallo,

Ich habe es geschafft noch mal in meine alten Sourcen zu schauen. Tatsächlich habe ich damals nicht nur die kopierte (Vcl.)Printer.pas anders benannt, sonder auch die Klassen, Typen und Konstanten umbenannt. Eigentlich sieht mir das jetzt mehr wie nachprogrammiert (was ich heute nicht mehr machen würde) aus.
Wenn man auf das TPrinter. PageNumber verzichten kann, ist Peter’s Variante mitunter einfacher. Es kommt auf die Umgebung an.
Ich bin jetzt noch auf eine Idee gekommen um das Problem mit abhängigen Units zu umgehen.

Delphi-Quellcode:
unit Vcl.Printers.Help;

interface

uses
  System.Classes;

var
  OnPrinterBetweenPage: TNotifyEvent;

implementation

end.
Delphi-Quellcode:
unit Vcl.Printers;
...
implementation

uses
...
  Vcl.Consts,
  Vcl.Printers.Help;
...
procedure TPrinter.NewPage;
begin
  CheckPrinting(True);
  EndPage(DC);
  if Assigned(OnPrinterBetweenPage) then
    OnPrinterBetweenPage(self);
  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;
Damit bleibt der Interface-Abschnitt von
Delphi-Quellcode:
Vcl.Printers
unverändert. Man würde dann vor dem Drucken dem
Delphi-Quellcode:
OnPrinterBetweenPage
eine Methode zuweisen und in dieser wenn nötig das Umschalten der Ausrichtung erledigen.

einbeliebigername.

haentschman 1. Jul 2019 14:18

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Moin...8-)
Zitat:

gibt es eine Möglichkeit innerhalb eines Druckauftrages von Portrait auf Landscape umzuschalten?
In den heutigen Zeiten von FastReport (in Delphi dabei und hat mit der Problemstellung keine Probleme :zwinker:) und Co. auf TPrinter zurückzugreifen ist imho "OldSchool" :zwinker: Wäre ein Reportgenenerator eine Alternative?

tomkupitz 2. Jul 2019 10:14

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Eine Lösung ist folgende Helper Klasse, die in die Vcl.Printers.pas eingebaut werden muss:

Delphi-Quellcode:
  ...

  TPrinterHelper = class Helper for TPrinter
  public
    procedure NewPageEx(Orientation: Integer);
  end;
  ...

[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinterHelper.NewPageEx(Orientation: Integer);
begin
  CheckPrinting(True);
  EndPage(DC);

  FDevMode^.dmOrientation:=Orientation; //DMORIENT_PORTRAIT DMORIENT_LANDSCAPE

  if ResetDC(Canvas.Handle, FDevMode^)=0 then
    Exit;

  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;
Aufruf dann:

Delphi-Quellcode:
procedure TForm1.FormClick(Sender: TObject);
begin
  Printer.Orientation:=poPortrait;

  Printer.BeginDoc;

  Printer.Canvas.TextOut(100, 100, 'Seite 1');

  Printer.NewPageEx(DMORIENT_LANDSCAPE);

  Printer.Canvas.TextOut(100, 100, 'Seite 2');

  Printer.EndDoc;
end;
Beste Grüße

TurboMagic 2. Jul 2019 20:55

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Zitat von p80286 (Beitrag 1435631)
oder aber Du schickst die Druckersteuerdaten und die zu druckenden Daten direkt an den Drucker (falls das überhaupt noch geht?)

Ja das geht noch. Eine private Anwendung von mir steuert auf dem Weg ESC/P fähige Kassendrucker an, da diese Sonderfunktionen
haben die man mit normalem GDI Druck so m.W. nicht ansteuern kann: Bon Cut zum Beispiel.

TurboMagic 2. Jul 2019 20:58

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Vielleicht mag auch mal jemand in QP einen "feature request" für das Ursprüngliche Problem
des gewünschten Änderns der Seitenorientierung innerhalb eines Druckauftrages erstellen?

Damit in irgend einer Zukunft nichts mehr an printers.pas geändert werden muss...

Detlev 13. Nov 2021 20:22

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Ich habe die von Tomkupitz in #16 vorgeschlagene Lösung verwendet und es funktioniert! Erst mal vorab: Vielen Dank. Elegante Lösung!

Ich habe dazu natürlich eine lokale Kopie der Vcl.printers.pas in meinem Projektordner gespeichert. Delphi verwendet auch automatisch diese lokale Kopie.

Ich habe aber doch noch zwei Fragen, einfach um was dazu zu lernen:

(1)

Delphi Tokyo 10.2 gibt zahlreiche Warnmeldungen des Typs "[dcc32 Warnung] Vcl.Printers.pas(943): W1025 Sprach-Feature wird nicht unterstützt: 'Benutzerdefiniertes Attribut'" auf den Zeilen mit Attribut aus.

Kann ich die Warnungen einfach ignorieren? Was bedeuten sie überhaupt? Wieso werden die Attribute nicht unterstützt, wenn sie doch exakt so in der VCL.Printers stehen?

(2)

Ich habe eine analoge Lösung ausprobiert, bei der ich die Prozedur statt als Helper-Klasse direkt in TPrinter implementiere. Ansonsten exakt gleich. Geht aber nicht: Fataler Fehler beim Compilieren ohne Angabe einer Zeile.

Warum muss es ausgerechnet eine Helper-Klasse sein? Warum kann man nicht eine eigene Prozedur in TPrinter einfügen?! Ich möchte es nur gerne verstehen.

Code:
...
 public
    constructor Create;
    destructor Destroy; override;
    procedure Abort;
    procedure BeginDoc;
    procedure EndDoc;
    procedure NewPage;
    procedure NewPageWithOrientation(AOrientation: Integer); // added!
    procedure Refresh;
...
// original
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.NewPage;
begin
  CheckPrinting(True);
  EndPage(DC);
  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;

// added
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.NewPageWithOrientation(AOrientation: Integer);
begin
  CheckPrinting(True);
  EndPage(DC);

  FDevMode^.dmOrientation := AOrientation;

  StartPage(DC);
  Inc(FPageNumber);
  Canvas.Refresh;
end;

TurboMagic 14. Nov 2021 13:56

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Keine Ahnung auf die Schnelle: aber existiert schon ein QP Report für die Problemstellung?
Kann, falls nicht, jemand den erstellen? Dann müssen wir in Zukunft evtl. keine eigenen
Bugfixes mehr anbringen...

Detlev 14. Nov 2021 15:53

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Sorry, keine Ahnung, was ein QP ist oder wie man den macht.

Vielleicht findet sich ja noch jemand, der meine Fragen beantworten kann.

TurboMagic 14. Nov 2021 16:09

AW: TPrinter: Portrait auf Landscape umzuschalten
 
Zitat:

Zitat von Detlev (Beitrag 1497545)
Sorry, keine Ahnung, was ein QP ist oder wie man den macht.

Vielleicht findet sich ja noch jemand, der meine Fragen beantworten kann.

QP steht für Quality Portal, das Jira basierte Bugtracking System für Delphi.
Logge dich doch mal mit deinem EDN Account hier ein:

https://www.quality.embarcadero.com

Dort kannst du nach Stichworten suchen und wenn für dein Problem damit noch kein
Bugreport vorhanden ist, dann bitte auf den prominenten Button am oberen Seitenrand
klicken und das Formular ausfüllen...

Grüße
TurboMagic


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:10 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz