![]() |
TPrinter: Portrait auf Landscape umzuschalten
Hallo,
gibt es eine Möglichkeit innerhalb eines Druckauftrages von Portrait auf Landscape umzuschalten? Folgendes funktioniert nicht:
Delphi-Quellcode:
Danke und beste Grüße
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; |
AW: TPrinter: Portrait auf Landscape umzuschalten
Nö das geht nicht:
Zitat:
Gruß K-H |
AW: TPrinter: Portrait auf Landscape umzuschalten
Hallo,
Zitat:
Die Orientation bei einem Druckjob kann nur außerhalb einer Seite umgestellt werden. Das Problem ist das NewPage:
Delphi-Quellcode:
Das Umschalten müsste zwischen
procedure TPrinter.NewPage;
begin CheckPrinting(True); EndPage(DC); StartPage(DC); Inc(FPageNumber); Canvas.Refresh; end;
Delphi-Quellcode:
und
EndPage(DC);
Delphi-Quellcode:
stattfinden. Meine Lösung war damals, den Sourcecode von TPrinter kopieren und das NewPage in EndPage und StartPage zerlegen.
StartPage(DC);
einbeliebigername. |
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
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; |
AW: TPrinter: Portrait auf Landscape umzuschalten
Ich habe mal Folgendes in Printers.pas eingebaut:
Delphi-Quellcode:
Leider erhalte dabei die Fehlermeldung:
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; [dcc32 Fataler Fehler] Vcl.Printers.pas(1550): F2613 Unit 'Vcl.Dialogs' nicht gefunden. |
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
|
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
2. Ich erhalte dann den Fehler: Zu wenig Arbeitsspeicher. |
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
Klicke doch auf die Fehlermeldung. Dann wirst du sehen, in welcher Zeile da etwas fehlt. Zitat:
|
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
Zitat:
|
AW: TPrinter: Portrait auf Landscape umzuschalten
Wie ist DC deklariert?
Delphi-Quellcode:
EndPage(DC);
|
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. |
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
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. |
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 |
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:
Damit bleibt der Interface-Abschnitt von
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;
Delphi-Quellcode:
unverändert. Man würde dann vor dem Drucken dem
Vcl.Printers
Delphi-Quellcode:
eine Methode zuweisen und in dieser wenn nötig das Umschalten der Ausrichtung erledigen.
OnPrinterBetweenPage
einbeliebigername. |
AW: TPrinter: Portrait auf Landscape umzuschalten
Moin...8-)
Zitat:
|
AW: TPrinter: Portrait auf Landscape umzuschalten
Eine Lösung ist folgende Helper Klasse, die in die Vcl.Printers.pas eingebaut werden muss:
Delphi-Quellcode:
Aufruf dann:
...
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;
Delphi-Quellcode:
Beste Grüße
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; |
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
haben die man mit normalem GDI Druck so m.W. nicht ansteuern kann: Bon Cut zum Beispiel. |
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... |
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; |
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... |
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. |
AW: TPrinter: Portrait auf Landscape umzuschalten
Zitat:
Logge dich doch mal mit deinem EDN Account hier ein: ![]() 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 06:25 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz