Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Ändern der Druckeinstellungen beim Drucken von PRN-Dateien (https://www.delphipraxis.net/159667-aendern-der-druckeinstellungen-beim-drucken-von-prn-dateien.html)

DelphiApostel 7. Apr 2011 11:28

Ändern der Druckeinstellungen beim Drucken von PRN-Dateien
 
Liste der Anhänge anzeigen (Anzahl: 2)
Hallo,

mit der unten aufgeführten Funktion ist es möglich eine PRN-Datei direkt zu drucken (über einen zuvor ausgewählten Drucker). Auch nach zahlreichen Versuchen (und ausgiebigen Recherchen im Internet) gelingt es mir leider nicht vor dem Drucken die Druckeinstellungen zu ändern (wie Anzahl der Kopien, Druckerschacht, Orientation usw...).
Laut einer MSDN-FAQ werden die Druckeinstellungen in der PRN-Datei favorisiert, so dass die Standardeinstellungen des Druckers nicht berücksichtigt werden.

Ich weiß wie man temporär (über Delphi Printer-Objekt und über die JEDI-Unit JclPrint) oder global (über die WinSpool-Funktionen "DocumentProperties" und "SetPrinter") die Druckereinstellungen ändern kann. Das klappt ohne Probleme.

Aber ich kann einfach nicht daran glauben, dass man beim Drucken von PRN-Dateien (mit OpenPrinter und WritePrinter) keinen Druckerschacht vorgeben oder ihn nachträglich ändern kann!

Die Funktion, die ich oben erwähnt habe:
Delphi-Quellcode:
  Printer.PrinterIndex := PrIndex; //einen Drucker auswählen
  Printer.GetPrinter(Device, Driver, Port, hDeviceMode);

  If Not WinSpool.OpenPrinter(@Device, hPrinter, nil) Then Exit;

  DocInfo.pDocName := 'C:\Druckdatei.prn'; //die Datei, die an einen Drucker weitergeleitet werden soll
  DocInfo.pOutputFile := Nil;
  DocInfo.pDatatype :='RAW';

  StartDocPrinter(hPrinter, 1, @DocInfo);

  StartPagePrinter(hPrinter);

  //die PRN-Datei mit WritePrinter ausdrucken:
  System.Assign(f, string(sFileName));
  try
    Reset(f, 1);
    GetMem(Buffer, cBUFSIZE);
    While Not Eof(f) Do
    begin
      Blockread(f, Buffer^, cBUFSIZE, Count);
      If Count > 0 Then
      begin
        If Not WritePrinter(hPrinter, Buffer, Count, BytesWritten) Then
        begin
          EndPagePrinter(hPrinter);
          EndDocPrinter(hPrinter);
          WinSpool.ClosePrinter(hPrinter);
          FreeMem(Buffer, cBUFSIZE);
          Exit;
        end;
      end;
    end;
    FreeMem(Buffer, cBUFSIZE);
    EndDocPrinter(hPrinter);
    WinSpool.ClosePrinter(hPrinter);
  finally
    System.CloseFile(f);
  end;

Das Drucken von einfachem Text funktioniert ja (auch mit Vorgabe des Druckerschachts und Anzahl der Kopien). Hier ein Beispiel mit JCLPrint:

Delphi-Quellcode:

procedure TForm1.Button1Click(Sender: TObject);
var
  PSet:TJclPrintSet;
begin
  PSet:= TJclPrintSet.Create;
  Pset.Copies:=2; //Anzahl der Kopien
  Pset.BinIndex:=4; //Druckerschacht

  printer.Orientation:=poLandscape;
  printer.BeginDoc;
  printer.Canvas.textout(0,0,'Ein Test'); //kommt im Schacht Nr. 4 zwei mal raus!
  printer.EndDoc;
end;
Ich bin euch für jeden Hinweis dankbar!

Die Hintergrundinformationen findet ihr im Anhang:

omata 7. Apr 2011 13:44

AW: Ändern der Druckeinstellungen beim Drucken von PRN-Dateien
 
Also, was du hier an Code präsentierst, ist einfach unterirdisch. Kein wunder, dass dir keiner hilft (weil das eigentlich gar nicht geht!)
Sorry, aber das musste ich vorher loswerden.

Hier mal eine Routine, die auch nachvollziehbar und startbar ist:
Delphi-Quellcode:
uses Printers, WinSpool;

procedure PrintTest;
const cBUFSIZE = 1000;
var Device, Driver, Port:PAnsiChar;
    hDeviceMode, hPrinter, BytesWritten:Cardinal;
    DocInfo : TDocInfo1;
    f:File;
    sFileName:string;
    Buffer:Pointer;
    Count:integer;
    stop:boolean;
    DevMode : PDeviceMode;
begin
  Driver:=nil;
  Port:=nil;
  Printer.PrinterIndex := 0; //einen Drucker auswählen
  Printer.GetPrinter(Device, Driver, Port, hDeviceMode);

  DevMode := GlobalLock(hDeviceMode);
  DevMode^.dmDefaultSource:=1; // <- Versuch mal hier den Schacht einzustellen.

  if WinSpool.OpenPrinter(@Device, hPrinter, nil) then begin
    DocInfo.pDocName := 'C:\temp\Druckdatei.prn'; //die Datei, die an einen Drucker weitergeleitet werden soll
    DocInfo.pOutputFile := nil;
    DocInfo.pDatatype :='RAW';

    StartDocPrinter(hPrinter, 1, @DocInfo);
    StartPagePrinter(hPrinter);

    //die PRN-Datei mit WritePrinter ausdrucken:
    System.AssignFile(f, sFileName);
    try
      Reset(f, 1);
      GetMem(Buffer, cBUFSIZE);
      stop:=false;
      while not Eof(f) and not stop do begin
        Blockread(f, Buffer^, cBUFSIZE, Count);
        if Count > 0 then begin
          if not WritePrinter(hPrinter, Buffer, Count, BytesWritten) then begin
            EndPagePrinter(hPrinter);
            stop:=true;
          end;
        end;
      end;
      FreeMem(Buffer, cBUFSIZE);
    finally
      System.CloseFile(f);
    end;
    EndDocPrinter(hPrinter);
    WinSpool.ClosePrinter(hPrinter);
  end;
end;

DelphiApostel 8. Apr 2011 08:42

AW: Ändern der Druckeinstellungen beim Drucken von PRN-Dateien
 
@omata: ich habe gedacht, dass der wichtigste Teil des Quellcodes ausreichen würde, um das Problem zu verstehen. Ich sehe aber auch ein, dass eine, ohne weitere Anpassungen startbare, Routine/Funktion sehr viel hilfreicher ist. Ich werde in Zukunft darauf achten.

Nun zurück zu meinem Problem.
Dein Tipp funktioniert leider nicht. Übrigens hast du die Fields-Maskierung vergessen:
Delphi-Quellcode:
  ...
  DevMode := GlobalLock(hDeviceMode);
  DevMode^.dmDefaultSource:=1;
  DevMode^.dmFields := DevMode^.dmFields or DM_DEFAULTSOURCE; //dmFields-Maskierung
  ...
Die Druckeinstellungen im PRN-Dokument werden hier bevorzugt. Die Windows Druckeinstellungen (die man mit dem oberen Code einstellt) werden nicht berücksichtigt. Die Druckaufträge, die vom PostScript RAW-Drucker des Clients kommen (siehe mein Diagramm im Anhang), müssen an unterschiedliche Drucker und auf unterschiedliche Druckerschächte umgeleitet werden (unabhängig vom Treiber des RAW-Druckers).

Da die Priorität anscheinend nicht geändert werden kann, habe ich mir gedacht man könnte doch den Text im Buffer analysieren/auswerten :idea:. Kommt im Buffer eine Zeichenkette mit "MediaPosition" (siehe unten) vor, wird diese dynamisch verändert und anschließend mit WritePrinter an den Drucker geschickt (in den PRN-Dateien wird mit MediaPosition der Druckerschacht vorgegeben).

Auszug aus einer PRN-Datei (PostScript Dialect):
Code:
%%BeginFeature: *InputSlot Fach 5
<</ManualFeed false /MediaPosition 5>> setpagedevice  //für Schacht 3 muss MediaPosition 5 durch MediaPosition 3 ersetzt werden!
%%EndFeature
Nachdem ich die Idee ausprobiert habe, werde ich die Ergebnisse hier beschreiben.8-)

hathor 8. Apr 2011 09:05

AW: Ändern der Druckeinstellungen beim Drucken von PRN-Dateien
 
Habe ich das richtig verstanden:
Du hast NUR das PRN-File und NICHT die NUTZDATEN?

Wäre es nicht einfacher, die NUTZDATEN aus dem PRN-File herauszufiltern und neu abzuspeichern?
Dieses neue File kannst Du dann drucken mit dem ursprünglichen Authoring-Programm, so wie Du es gerne hättest.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:26 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