Seite 1 von 2

Mehrere Dokumente hinereinander drucken

Verfasst: Di, 13. Mär 2007 11:01
von notloesung
Hallo,

habe etwas was mir keine Ruhe gibt - vielleicht ist es einfach nur ein Verständnisproblem (?).

Schreibe gerade eine Anwendung die unter anderem folgendes leisten muss:
Im xbpFileDialog kann der User mehrere Dateien (bisher PDFs) auswählen.
Diese müssen dann bevor sie im Programm weiter verarbeitet werden können umgewandelt werden (das Zielformat ist TIF). Dazu nutze ich einen Druckertreiben der diese Konvertierung unterstützt.
Vom xbpFileDialog bekomme ich einen Array mit den ausgewählten Dateien. Nun will ich sie mit dem o.g. Druckertreiber drucken.
Das klappt natürlich noch nicht :cry:
Bisher gehe ich folgendermaßen vor:

Code: Alles auswählen

   IF ! empty( aFiles )

      // Printerobjekt
      oPrinter := XbpPrinter():New()
      oPrinter:create( "Universal Document Converter" )

      IF oPrinter:status() != XBP_STAT_CREATE
         Msgbox( "Fehler !!!" )
         RETURN NIL
      ENDIF

      // Auswaehlen des Druckers und Setzen der Druckparameter.
      // Feststellen, ob wirklich gedruckt werden soll.
      IF XbpPrintDialog():new():create():display(oPrinter) == NIL
         lPrint := .F.
      ELSE
         lPrint := .T.
      ENDIF

      IF lPrint
         FOR i := 1 TO LEN( aFiles )
            // an dieser Stelle will ich nun alle ausgewählten
            // Dateien drucken - aber wie funktioniert das?
            oPrinter:startDoc()
            oPrinter:endDoc()
         NEXT
      ENDIF

   ENDIF
Mir ist einfach noch nicht klar ob das so funktionieren kann.
Vielleicht hat einer den entschiedenen Tipp für mich?

Danke,
Notloesung

Verfasst: Di, 13. Mär 2007 11:20
von andreas
Hi,

meiner Meinung nach bist du auf dem richtigen Weg. Jetzt musst du nur noch die Ausgabe zwischen den Startdoc() und Enddoc() machen. Hier kann ich dir aber nicht weiter helfen, da ich diese Ausgabe nicht nutze und mit Reportgenerator arbeite.

Verfasst: Di, 13. Mär 2007 11:24
von brandelh
Hi,

der XbpPrinter kann keine PDF Dokumente drucken.
Du must über RunShell() mit den richtigen Parametern (welche???) ein Programm aufrufen das das kann. z.B. acrobat reader
Wenn du syncron aufrufst kannst du das Ergebnis noch kontrollieren.
oder
du nutzt ein ActiveX Control (acrobat reader). Da gibt es unter der 1.90 AcitveX ein Beispiel. Ob das jetzt auch druckt weiß ich nicht, aber das müsste ja dann auch zu meistern sein.

Verfasst: Di, 13. Mär 2007 11:29
von notloesung
brandelh hat geschrieben: Da gibt es unter der 1.90 AcitveX ein Beispiel. Ob das jetzt auch druckt weiß ich nicht, aber das müsste ja dann auch zu meistern sein.
Ok, ich schaue mir das Bsp. mal an.
Irgendwie habe ich befürchtet das dass nicht ohne Umwege funktionieren kann :roll:

Notloesung

Verfasst: Di, 13. Mär 2007 11:34
von Jan
Hallo,

ich glaube Du gehst von falschen Voraussetzungen aus. XbpPrinter kann keine Dokumente/Bilder/etc. ausdrucken. Außer Du fügst Sie in den PresSpace ein, der den Ausdruck beinhaltet.

Du müstest also die Tifs da rein legen, dann müsste es mit dem Drucken klappen.

Aber warum druckst Du die pdf nicht direkt über ActiveX oder RunShell aus? Dann sparst Du Dir auch die konvertiererei.

Jan


Edit: Na toll, Hubert hatte die schnelleren Finger. Man sollte halt keine Kundengespräche während des Schreibens annehmen 8)

Verfasst: Di, 13. Mär 2007 13:16
von notloesung
Jan hat geschrieben:Aber warum druckst Du die pdf nicht direkt über ActiveX oder RunShell aus? Dann sparst Du Dir auch die konvertiererei.
Hallo Jan,

das mit ActiveX würde mich brandend interessieren.
Leider finde ich bisher noch kein brauchbares Beispiel dafür.
Bis dato habe ich nichts Großartiges mit ActiveX gemacht,
würde mich aber gern der Herausforderung stellen.

Um das mit RunShell zu machen fehlt mir einfach die Erfahrung wie ich das mit einem Druckertreiber bewältigen könnte, was aber ‚ne tolle Sache währe.

Vielleicht hast du mal einen Tipp für mich wie ich dass angehen könnten.

Gruß,
Notloesung

Verfasst: Di, 13. Mär 2007 13:57
von Lewi
Moin,
versuche es mal damit:


Code: Alles auswählen


DLLFUNCTION FindExecutableA( cFileExtention, cPath, @cExe ) USING STDCALL FROM SHELL32.DLL
DLLFUNCTION ShellExcuteA( nWinHandle,  cMode, cExe, cFile, cDir, nShow) USING STDCALL FROM SHELL32.DLL


#define SHELL_OPEN      "open"
#define SHELL_PRINT     "print"
#define SHELL_EXPLORE   "explore"

// ShowWindow Modes
#define SW_HIDE             0
#define SW_SHOWNORMAL       1
#define SW_NORMAL           1
#define SW_SHOWMINIMIZED    2
#define SW_SHOWMAXIMIZED    3
#define SW_MAXIMIZE         3
#define SW_SHOWNOACTIVATE   4
#define SW_SHOW             5
#define SW_MINIMIZE         6
#define SW_SHOWMINNOACTIVE  7
#define SW_SHOWNA           8
#define SW_RESTORE          9
#define SW_SHOWDEFAULT      10

Func PrintPdf( cPdfFile )

if file( cPdfFile )
   RunDefaultShellProg( cPdfFile, SHELL_PRINT, SW_HIDE )
endif
Return ( NIL )

FUNC RunDefaultShellProg(cFile, cMode, nShow)
LOCAL cPath :=""
Local  cExe := space(256)
LOCAL nPos, nRet

   nPos := rat("\", cFile)
   if nPos > 0
      cPath := substr(cFile, 1, nPos)
      cFile := substr(cFile, nPos+1)
   endif

   nRet := FindExecutableA(cFile, cPath, @cExe)
   if nRet <= 32
      RETURN nRet
   endif

   nRet := ShellExecuteA(AppDesktop():getHWnd(), cMode, cExe, cFile, cPath, nShow)
RETURN nRet 
Gruß, Olaf

Verfasst: Di, 13. Mär 2007 14:11
von brandelh
Hallo,

Die Lösung von Levi holt sich die Infos, die in Windows hinterlegt sind.
Diese kann man auch direkt aus dem Dateiobjekt auslesen, falls man die Parameter wissen will:

Explorer - Extras - Ordneroptionen - Dateitypen - PDF - ERWEITERT

Nun sieht man (zumindest bei mir) eine Listbox mit Vorgängen.

PRINT -> einfach drucken = ....exe" /p /h "%1"

Ich denke /P steht für drucken,
/h für Acrobat nicht anzeigen
"%1" hier muss der komplette PDF Name mit Pfad rein, am Besten mit " wegen Blanks im Namen.

Lewis Lösung ist eleganter und vielseitiger (nicht nur PDF), aber vielleicht hilft die Info ja.

Verfasst: Di, 13. Mär 2007 14:25
von brandelh
Hi,

die ActiveX Variante ist nicht so berauschend.
Ich habe gerade das Xbase++ Beispiel (wieder) angesehen.
Das Öffnen des ersten Dokumentes braucht ewig.

Verfasst: Di, 13. Mär 2007 14:42
von brandelh
Hi,

hier habe ich auch einige Infos zum Drucken auf bestimmten Druckern gefunden, (mehr als eigene Gedanken Stütze ;-) ):
In der Developers FAQ steht in etwa:

How To: Drucken aus der Commandozeile:

Wie in der 'Acrobat Developer FAQ' dokumentiert dient der Paramter /t dem direkten Drucken:

Drucken auf einem Netzwerkdrucker mit Druckertreiber und IP-Adresse:

Code: Alles auswählen

AcroRd32.exe /t "C:\test.pdf" "\\servername\printername" "AdobePS Tektronix Phaser 840" "123.45.678.910"
oder auch nur auf den Drucker ohne Treibername und ohne IP:

Code: Alles auswählen

AcroRd32.exe /t "C:\test.pdf" "\\servername\printername"
und hier stehen diese Infos:

http://support.adobe.com/devsup/devsup. ... /52080.htm

ich hatte einmal ein PDF mit anderen Parametern, dieses ist aber nicht mehr verfügbar.

Verfasst: Mi, 14. Mär 2007 7:53
von notloesung
Lewi hat geschrieben:

Code: Alles auswählen

RunDefaultShellProg( cPdfFile, SHELL_PRINT, SW_HIDE )
Hallo Olaf,

der obere Aufruf funktioniert bei mir noch nicht. Merkwürdig ist dass absolut nichts passiert. Kein Druck und keine Fehlermeldung.
Das hier funktioniert dagegen einwandfrei:

Code: Alles auswählen

RunDefaultShellProg( cPdfFile, SHELL_OPEN, SW_SHOWDEFAULT )
Woran mag das wohl liegen?

Wie ich eben gesehen habe ist der Rückgabewert von ShellExecuteA 31. Da schint etwas nicht zu stimmen(?).

Gruß,
Notloesung

Verfasst: Mi, 14. Mär 2007 8:33
von brandelh
Hi,

ruf es doch mal sichtbar auf. Also SW_HIDE durch SW_SHOWDEFAULT ersetzen. Eventuell sieht du dann eine Fehlermeldung.

Verfasst: Mi, 14. Mär 2007 8:49
von notloesung
brandelh hat geschrieben:ruf es doch mal sichtbar auf. Also SW_HIDE durch SW_SHOWDEFAULT ersetzen. Eventuell sieht du dann eine Fehlermeldung.
Hallo,

ups, das habe ich vergessen zu erwähnen.
Das habe ich schon probiert. Es ändert nichts am Verhalten.

Der Rückgabewert von ShellExecuteA ist immer 31.
Laut der Microsoft Doku ist es folgendes:
aus: http://www.microsoft.com/germany/msdn/library/visualtools/vb6/AusVisualBasicHerausDokumenteInZugehoerigenAnwendungenOeffnen.mspx?mfr=true hat geschrieben:Die Funktion ShellExecute berichtet in ihrem Rückgabewert über den Erfolg des versuchten Aufrufs: Ist der Rückgabewert größer als 32, war der Aufruf erfolgreich. Besondere Aufmerksamkeit verdient dabei der Rückgabewert 31, dem der symbolische Konstantenname SE_ERR_NOASSOC zukommt: Gibt ShellExecute diesen Wert zurück, so besteht keine Anwendungs-Zuordnung zwischen dem angegebenen Dateityp und einem Anwendungsprogramm.
Das kann aber nicht passen. Die Parameter beim Aufruf stimmen. Immerhin kann die Datei ja geöffnet werden.

Notloesung

Verfasst: Mi, 14. Mär 2007 8:52
von Günter Beyes
Hallo,

der Rückgabewert 31 (SE_ERR_NOASSOC) bedeutet laut MSDN

"Mit der gegebenen Dateinamenserweiterung ist keine Anwendung verknüpft. Dieser Fehler wird auch zurückgegeben, wenn man eine nicht druckbare Datei zu drucken versucht."

Kommt der Fehler von ShellExecuteA(), oder bereits von FindExecutableA() ?


Gruß,
Günter

Verfasst: Mi, 14. Mär 2007 9:00
von Lewi
Sorry, ich hatte den Code nicht getestet. Dies habe ich jetzt nachgeholt und meine Lösung korrigiert. Mit dem nachfolgenden Code kann ich drucken:

Code: Alles auswählen

DLLFUNCTION ShellExecuteA( nWinHandle,  cMode, cFile, cDir, nShow) USING STDCALL FROM SHELL32.DLL


#define SHELL_OPEN      "open"
#define SHELL_PRINT     "print"
#define SHELL_EXPLORE   "explore"

// ShowWindow Modes
#define SW_HIDE             0
#define SW_SHOWNORMAL       1
#define SW_NORMAL           1
#define SW_SHOWMINIMIZED    2
#define SW_SHOWMAXIMIZED    3
#define SW_MAXIMIZE         3
#define SW_SHOWNOACTIVATE   4
#define SW_SHOW             5
#define SW_MINIMIZE         6
#define SW_SHOWMINNOACTIVE  7
#define SW_SHOWNA           8
#define SW_RESTORE          9
#define SW_SHOWDEFAULT      10


Func PrintPdf( cPdfFile )

if file( cPdfFile )
   RunDefaultShellProg( cPdfFile, SHELL_PRINT, SW_HIDE )
endif
Return ( NIL )

FUNC RunDefaultShellProg(cFile, cMode, nShow)
   LOCAL  nRet

   nRet := ShellExecuteA(AppDesktop():getHWnd(), cMode, cFile, "", nShow)

  If ! (nret > 32)
   Msgbox("Fehlercode: " + Str( nRet ))
endif

RETURN nRet
Gruß, Olaf

Verfasst: Mi, 14. Mär 2007 9:01
von notloesung
Günter Beyes hat geschrieben:Kommt der Fehler von ShellExecuteA(), oder bereits von FindExecutableA() ?
Hi,

der Fehler wir erst von ShellExecuteA verursacht.

Gruß,
Notloesung

Verfasst: Mi, 14. Mär 2007 9:08
von Günter Beyes
Hmm.

Erscheint beim Rechtsklick auf die PDF-Datei der Eintrag "Drucken" im Kontextmenü, und druckt es, wenn du ihn aufrufst?

Ist der Defaultdrucker bereit?

Günter

Verfasst: Mi, 14. Mär 2007 9:13
von Lewi
Moin Günter,
mit dem korrigiertem Code sollte man eine PDF-Datei drucken können, wenn Acrobat auf dem Rechner installiert ist.

Der Fehler war, das der Aufruf "FindExcutable" in Zusammenhang mit "SW_PRINT" der falsche Ansatz ist.

Sobald sich über das Kontext-Menu über "drucken" eine Datei drucken lässt, sollte der neue Code funktionieren.

Gruß, Olaf

PS: Wie geschrieben, bei mir funktioniert die Lösung!

Verfasst: Mi, 14. Mär 2007 16:06
von Rolf Ramacher
Hallo,

gibt es hierzu nicht eine Methode von xbase?? xbppdf oder so ähnlich

Verfasst: Mi, 14. Mär 2007 16:39
von brandelh
Hallo,

es gibt einen Zusatzbibliothek XppPDF, die wird aber nicht zum Drucken von bestehenden PDFs verwendet, sonder zum Erstellen von neuen PDFs ohne einen PDF-Druckertreiber.

Verfasst: Do, 15. Mär 2007 12:09
von notloesung
Hallo,

mit der Lösung von Olaf komme ich wunderbar hin.
Zumal es eben (fast) universell einsetzbar ist. Es lassen sich z.B. Word-Dokumente, .TXT-Dateien und vieles mehr auf die Selbe Art und Weise drucken.

Folgendes bekomme ich noch nicht hin:
Das Drucken klappt wie gesagt auch z.B. aus Word. Dabei wird Word kurz geöffnet, der Druck gestartet und Word schließt sich wieder automatisch. Bei Acrobat klappt das Schließen nicht automatisch. Bei Pdfs wird der Acrobat geöffnet, der Druck angestoßen aber der Acrobat schließt sich nicht automatisch – muss also manuell geschlossen werden. (Das gleiche Verhalten ist zu beobachten wenn aus dem Explorer (rechte Maustaste – Drucken) gedruckt wird.
Gibt es da wohl etwas Spezielles zu beachten?


Eine andere Sache beschäftigt mich noch mehr:
Wenn das Drucken mit der „Olafschen-Methode“ :) ausgelöst wird, so wird immer über den Standard Drucker gedruckt.
Mein Druck muss immer über einen speziellen Drucker laufen, der nicht unbedingt der Standarddrucker sein muss.
Gibt es eine Möglichkeit abzufragen welcher Drucker auf dem Rechner der Standarddrucker ist. Ich denke daran im Programm abzufragen ob der Drucker XYZ der Standarddrucker ist. Falls nicht dann würde ich mir gerne den Standarddrucker merken, den Drucker XYZ als Standarddrucker definieren, den Druck anstoßen und danach den vorherigen Drucker wieder als Standarddrucker setzen. Ist wohl so etwas möglich?

Gruß,
Notloesung

Verfasst: Do, 15. Mär 2007 12:18
von Martin Altmann
Hallo Jarek,
das geht wunderbar mit der PrinterAPI, die Du auf der Seite von Phil Ide findest.

Viele Grüße,
Martin

Verfasst: Do, 15. Mär 2007 13:03
von Lewi
Eine Lösung zum automatischem Beenden von Anwenungen hat Jimmy gepostet: http://www.xbaseforum.de/viewtopic.php?t=947

Für das automatische Beenden von Acrobat nach dem Drucken sollte Dir der Lösungsansatz von Jimmy weiter helfen.

Gruß, Olaf

Verfasst: Do, 15. Mär 2007 13:26
von Rolf Ramacher
Hallo notloesung,


du kannst ja beim drucken mit xbpprintdialog arbeiten. Dann werden die installierten Drucker angzeigt, bei dem du dann den Drucker auswählen kannst.

Verfasst: Do, 15. Mär 2007 13:37
von Lewi
Hallo Rolf,
die xbpPrinterDialog()-Klasse wird hier nicht weiter helfen, da der Druck über eine API-Funktion erfolgt. Der Einsatz dieser Klasse macht nur dann Sinn, wenn der Duck über ein xBase Presentation-Space Object (mittels Verknüpfung eines Druckers zu einem Presentation space) erfolgt.

Oder anders gesagt, über xbpPrinterDialog() kann ein Drucker nicht zum Windows Standard-Drucker gesetzt werden.

Gruß, Olaf