Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Acrobat Reader mit vb wieder schließen

1,446 views
Skip to first unread message

Ingo R. Kirchner

unread,
Aug 10, 2006, 5:10:27 PM8/10/06
to
Hallo vb-Profi's,

in einem kleinen Tool drucke ich verschiedene PDF Dokumente per vb aus:

Ergebnis = Shell("C:\Programme\Adobe\Acrobat 6.0\Reader\AcroRd32.exe /p
/h abc.pdf)

Nun habe ich das Problem, daß ich den Acrobat Reader nicht wieder
geschlossen bekommen. Habe auch mal den Tipp mit Shell2hWnd und WM_close
probiert, funktioniert beim Taschenrechner oder Editor einwandfrei, aber
der Acrobat Reader nicht.

Hat jemand vielleicht eine Idee für mich.

Besten Dank im Voraus

Ingo

Ahmed Martens

unread,
Aug 11, 2006, 5:25:46 PM8/11/06
to
Hallo Ingo,

Am Thu, 10 Aug 2006 23:10:27 +0200 schrieb Ingo R. Kirchner:

> Hallo vb-Profi's,
>
> in einem kleinen Tool drucke ich verschiedene PDF Dokumente per vb aus:
>
> Ergebnis = Shell("C:\Programme\Adobe\Acrobat 6.0\Reader\AcroRd32.exe /p
> /h abc.pdf)

Um Dateien zu drucken verwende ich immer die ShellExecute-Api. Vorher
kann über ein Druckerdialog ein Drucker gewählt werden. Dieser wird
kurzfristig auf Standard umgestellt, damit mit ShellExecute auf diesen
gedruckt wird. Nach dem Druck wird auf den Originalstandarddrucker
zurückgestellt.

Google mal nach ShellExecute. Bei VB-Archiv hatte ich auch eine ganz
einfache Funktion gefunden um systemweit den Standarddrucker zu
wechseln. Leider habe ich diese nur im Büro. Montag könnte ich Dir diese
geben.

Gruß Ahmed
--
Antworten bitte nur in der Newsgroup.

Ingo R. Kirchner

unread,
Aug 12, 2006, 5:57:22 AM8/12/06
to
Hallo Ahmed,

vielen Dank für Deine Nachricht, aber da liegt ein Mißverständnis vor.
Ich möchte nicht ein PDF-Dokument neu erstellen via Drucker sondern ein
bestehendes PDF-Dokument oder mehrere über den normalen Standarddrucker
oder auch einen anderen Drucker auf Papier ausdrucken. Ein Modul zum
Wechseln, auch temporär, des Standarddruckers habe ich ja.
Das Funktioniert ja auch. Aber wenn du ein PDF-Dokument still im
Hintergrund ausdrucken willst geht das meines Erachtens mit Adobe Reader
mit den Parametern /p und /h + Dokumentname öffnen. Nur bleibt dann zum
Schluß eine Instanz des Readers offen, die ich auch durch Abfangen des
FensterHandles oder der TaskID irgendwie nicht wieder geschlossen
bekomme. Eigentlich kein Drama, aber wäre sauberer, wenn das kleine Tool
die von mir geöffnete Anwendung auch wieder schließen würde.

Gruß Ingo

Ahmed Martens schrieb:

Ingo Moch

unread,
Aug 12, 2006, 8:27:25 AM8/12/06
to
Ingo R. Kirchner meint:

> in einem kleinen Tool drucke ich verschiedene PDF
> Dokumente per vb aus:
>
> Ergebnis = Shell("C:\Programme\Adobe\Acrobat
> 6.0\Reader\AcroRd32.exe /p /h abc.pdf")

Ahmeds Hiweis auf ShellExecute war schon gut ... aber
nur als "BTW", da es mit deinem konkreten Problem
zu tun hat. Mit ShellExecute() machst Du dich
unabhängig vom Installationsort (besonders wenn der
Hersteller so bl.. ist, und die Versionsnummer in den
Standard-Verzeichnisnamen aufnimmt) und auch ist es
nicht mehr wichtig, welche Parameter der Hersteller
verwendet, ob er sie ggf. in spaeteren Versionen
aendert oder der Anwender eine Alternative zum
Adobe-Reader verwendet. So nebenbei vermeidest Du
das Problem mit den Leerzeichen im Dateinamen.

Bei mir jedenfalls wuerde da der Laufzeitfehler 53
(Datei nicht gefunden) erscheinen, weil bei mir die
Version 7 im vorgeschlagenen Pfad installiert ist.

> Nun habe ich das Problem, daß ich den Acrobat Reader
> nicht wieder geschlossen bekommen. Habe auch mal den
> Tipp mit Shell2hWnd und WM_close probiert,
> funktioniert beim Taschenrechner oder Editor
> einwandfrei, aber der Acrobat Reader nicht.

Shell2hWnd?

Meinst Du etwa
http://www.vbarchiv.net/archiv/tipp_details.php?pid=367%5C
?

Ansonsten ... machst Du das SendMessange(..., WM_CLOSE,
...) direkt nach dem Shell() oder wartest Du ein paar
Sekunden?

Wenn ich mich recht erinnere, gibt es beim
AdobeReader auch einen Aufrufparamter, der das
Schliessen des Fensters nach dem Drucken
veranlasst ... leider finde ich da nichts mehr zu.

HTH
Ingo
--
„Die Genialität einer Konstruktion liegt in ihrer Einfachheit. Kompliziert
bauen kann jeder.“
(Sergei Pawlowitsch Koroljow)

Ingo R. Kirchner

unread,
Aug 12, 2006, 9:45:26 PM8/12/06
to
Hallo Ingo, ja das ist genau di eFunktion die eben nicht funktioniert,
ich drucke ein paar hundert Dokumente in einer bestimmten Reihenfolge,
daher das Tool, funktioniert auch einwandfrei,es wird alles gedruckt,
nur eben zum schluss adobe nicht wieder geschlossen. sendmessage funzt
nicht.

trotzdem besten dank

ingo

Ingo Moch

unread,
Aug 13, 2006, 6:00:34 AM8/13/06
to
Hallo,

Ingo R. Kirchner meint:

> sendmessage funzt nicht.

ich glaube, es sit an der Zeit, uns mal den Code zu
zeigen.

Tschau

Ingo R. Kirchner

unread,
Aug 13, 2006, 11:05:46 AM8/13/06
to
Hallo Ingo,

claro hier der Code, ziemlich
simple:

**************************************************************
Dim Ergebnis
Dim lCounter As Long
For lCounter = 1 To ListView1.ListItems.count
If ListView1.ListItems(lCounter).Checked = True Then
Ergebnis = Shell(GetProfile(SetIniName(), "Pathes", "ACRp")
& " /p /h " & ListView1.ListItems(lCounter).Text)
End If

Next lCounter

****************************************************************

und hier die INI:

[Pathes]
ACRp = C:\Programme\Adobe\Acrobat 6.0\Reader\AcroRd32.exe

es werden einfach die in einem Listview als checked markierten Dokumente
beim Durchlauf nacheinander zum Druck gesendet.

Aber du kannst das selbst ziemlich einfach nachbauen, mit shell den
Acrobat Reader öffnen, oder eben auch die erwähnte shell2hwnd und mal
versuchen das Ding irgendwie wieder zu schließen. Brauchst gar nichts
drucken. Ich schaffe es nicht, den Acrobat Reader per code zu öffnen und
wieder ordentlich zu schließen. Wie gesagt, mit Notepad oder der
calc.exe geht das mit wm_close und sendmessage, mit dem Acrobat Reader
gelingt es mir nicht. Vielleicht stelle ich mich ja auch nur zu blöd an.

Gruß Ingo

Gert Wietzorek

unread,
Aug 13, 2006, 11:45:19 AM8/13/06
to
Hallo Ingo,


> Ich schaffe es nicht, den Acrobat Reader per code zu öffnen und
> wieder ordentlich zu schließen. Wie gesagt, mit Notepad oder der
> calc.exe geht das mit wm_close und sendmessage, mit dem Acrobat Reader
> gelingt es mir nicht. Vielleicht stelle ich mich ja auch nur zu blöd an.
>
> Gruß Ingo


Option Explicit
Private Declare Function FindClassWindow Lib "user32" Alias _
"FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As Long) _
As Long
Private Const WM_SYSCOMMAND = &H112
Private Const SC_CLOSE = &HF060
Private Declare Function PostMessage Lib "user32" _
Alias "PostMessageA" (ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) _
As Long
Private Declare Function ShellExecuteAPI Lib "shell32.dll" Alias _
"ShellExecuteA" (ByVal hwnd As Long, _
ByVal lpoperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nshowcmd As Long) _
As Long
Private Const SW_HIDE = 0

Public Function PrintDocument(byval documentAndpath$) as long
'Druckt jedes Dokument für das eine Druckverknüpfung in
'der Registry hinterlegt ist
PrintDocument=shellexecuteApi(0,"print",documentandpath,"",_
"",SW_HIDE)
end Function


Public function CloseClassWindow(ByVal class$) as boolean
'Acrobat=AdobeAcrobat
'Klassenname des Hauptfensters übergeben
'Liefert true zurück, falls ein Fenster gefunden wurde
'schließt das erste gefundene Fenster
Dim hwnd&
hwnd = FindClassWindow(class$, 0&)
If hwnd Then
CloseClassWindow=true
Call PostMessage(hwnd, WM_SYSCOMMAND, SC_CLOSE, ByVal 0&)
End If
End Sub

Gruß

Gert


--

------------------------------------------------
| Antworten nur in die Newsgroup, |
| die E-Mail Adressen existieren nicht! |
| |
| answers and questions only to the newsgroup,|
| the email adresses are not valid |
| |
| http://www.gwsoftware.de |
------------------------------------------------

Ingo R. Kirchner

unread,
Aug 13, 2006, 5:08:30 PM8/13/06
to
Hallo Gert,

vielen Dank, aber hast du das auch mal probiert, bei mir funktioniert
das nicht. Der druckt noch nicht mal mit dem Code. Wo trägst du denn
hier den Acrobat, die Parameter und das Dokument ein. Und wie rufst du
das Schließen auf. Gib doch mal ein Beispiel bei dem wir unterstellen
Acrobat unter "C:\Programme\Adobe\Acrobat 6.0\Reader\AcroRd32.exe" und
sagen wir mal das Dokument hiesse C:\Temp\abc.pdf, es soll im
Hintergrund gedruckt werden und Acrobat wieder geschlossen.

Gruß Ingo

Ingo Moch

unread,
Aug 13, 2006, 6:59:44 PM8/13/06
to
Hallo Ingo,

"Ingo R. Kirchner" schrieb:

> claro hier der Code, ziemlich simple:
>
> **************************************************************
> Dim Ergebnis
> Dim lCounter As Long
> For lCounter = 1 To ListView1.ListItems.count
> If ListView1.ListItems(lCounter).Checked = True Then
> Ergebnis = Shell(GetProfile(SetIniName(), "Pathes", "ACRp") &
> " /p /h " & ListView1.ListItems(lCounter).Text)
> End If
>
> Next lCounter
>
> ****************************************************************

ich meinte natuerlich inklusive dem Code-Anteil der
nicht funktioniert (sprich: Wie und wo Du versuchst
die Applikationmit WM_CLOSE zu schliessen).
"sendmessage funzt nicht." ist relativ nichtssagend.

Zudem ist es ganz sinnvoll, wenn Du auch die Fragen
beanwortest, die gestellt werden:

>>> Ansonsten ... machst Du das SendMessange(...,
>>> WM_CLOSE, ...) direkt nach dem Shell() oder
>>> wartest Du ein paar Sekunden?

Folgender Code funktioniert bei mir. Dabei werden zwei
Besonderheiten gemacht:

- Es wird so lange nach einem Fenster gesucht, bis es
gelistet ist.

- Fuer die Druck-Funktionalitaet wird nicht SendMessage(),
sondern PostMessage() verwendet. SendMessage "schiesst"
die Anwendung ab und es kommt (zumindest beim Adobe
Reader) zu einer Schutzverletzung. PostMessage() schreibt
nur in die MessageQueue, wird also von der Anwendung
nicht vorrangig bearbeitet.

BTW: Bei Beachtung von Applemanns dritten Gebot, waere dir
die Ursache relativ schnell klar geworden.

<CODE>
Option Explicit

Private Const SW_SHOWDEFAULT As Long = 10
Private Const WM_CLOSE As Long = &H10
Private Const WM_QUIT As Long = &H12

Private Declare Function ShellExecute _
Lib "shell32.dll" Alias "ShellExecuteA" ( _


ByVal hwnd As Long, _

ByVal lpOperation As String, _


ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _

ByVal nShowCmd As Long) As Long

Private Declare Function FindWindow _
Lib "user32" Alias "FindWindowA" ( _


ByVal lpClassName As String, _

ByVal lpWindowName As String) As Long

Private Declare Function PostMessage _
Lib "user32" Alias "PostMessageA" ( _


ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _

lParam As Any) As Long

Private Sub Form_Load()
Const sOPERATION As String = "PRINT"
Const sCLASSNAME As String = "AdobeAcrobat"
Dim nResult As Long
Dim i As Long
Dim bAppIsOpen As Boolean

' --- wenn die Applikation jetzt schon offen ---
' --- ist, dann hinterher nicht schliessen ---
bAppIsOpen = (FindWindow(sCLASSNAME, vbNullString) <> 0)

' --- Applikation starten ---
nResult = ShellExecute( _
0&, _
sOPERATION, _
"C:\Programme\Adobe\Acrobat 7.0\Help\DEU\Reader.pdf", _
vbNullString, _
vbNullString, _
SW_SHOWDEFAULT)

If (nResult > 32) Then
' --- Applikation konnte gestartet ---
' --- werden. Jetzt so lange nach ---
' --- einem Fenster der Klasse ---
' --- "AdobeAcrobat" suchen, bis ---
' --- es gefunden wird ---
If Not bAppIsOpen Then
Do
DoEvents
nResult = FindWindow(sCLASSNAME, vbNullString)
i = (i + 1) ' vorsichtshalber mit Abbruchkriterium
Loop Until (nResult <> 0) Or (i > 30000)

If (nResult <> 0) Then
' --- Wenn ein Fenster gefunden wurde schliessen ---
nResult = PostMessage(nResult, WM_CLOSE, ByVal 0&, ByVal 0&)
If (nResult <> 0) Then
MsgBox "Fenster konnte nicht geschlossen werden"
End If
Else
MsgBox "Kein Fenster gefunden"
End If
End If
Else
MsgBox "Dokument konnte nicht geöffnet werden"
End If
End Sub
</CODE>

HTH
Ingo


Ingo R. Kirchner

unread,
Aug 13, 2006, 7:41:08 PM8/13/06
to
Hallo Ingo,

also ich kenne das dritte Gebot leider nicht,ich geb auch nun mehr auf.
Bei mir funktioniert der von dir gelieferte Code nicht, benutze zwar den
Reader 6.0 aber das dürfte ja kein Unterschied machen. nresult = 5 und
damit konnte Dokument nicht ausdrucken, es tut sich auch gar nichts.

Wenn alles so klar ist warum sagst du es mir dann nicht einfach statt
mich auf irgednwelche Gebote zu verweisen. Also wenn ich hier schon mal
poste, dann hab ich schon alles mögliche probiert und suche hilfreiche
Unterstützung, nicht Egomania.

Troztdem vielen Dank

Ingo

Gert Wietzorek

unread,
Aug 14, 2006, 1:49:01 AM8/14/06
to
Ingo R. Kirchner schrieb:


Hallo Ingo,

ja, funktioniert bei mir. Wo Akrobat selbst ist, ist dabei völlig egal,
wenn es denn richtig installiert ist. Du übergibst ja nur den
Dokumentnamen....

Sieh nach unter HKEY_CLASSES_ROOT/.pdf
Den Eintrag des Standardwertes (bei mir AcroExch.Document) suchst Du
dann ebenfalls unter HKEY_CLASSES_ROOT

Darunter sollte es dann den Schlüssel Shell/Print geben, wie bei jeder
Anwendung, die das Drucken entsprechend unterstützt. Und da steht dann
alles drin, was Windows wissen muss, um das Dokument zu drucken. Ist
also der Schlüssel (z.B.
HKEY_CLASSES_ROOT/AcroExch.Document/shell/Print) bei Dir nicht da,
klappt es mit dem drucken nicht. Ansonsten kann Dir der Pfad zu Acrobat
und die Programmversion schnuppe sein, solange alles korrekt installiert
ist.


PrintDocument "c:\temp\abc.pdf"
CloseClassWindow "AdobeAcrobat"

Fertig

Möglicherweise musst Du nach PrintDocument noch eine Warteschleife
programmieren, um Acrobat nicht schon wieder zu schließen, bevor er
gedruckt hat.

Ahmed Martens

unread,
Aug 14, 2006, 2:18:11 AM8/14/06
to
Hallo Ingo,

ich drucke ein PDF-Dokument wie folgt:

1. Deklaration der API ShellExecute:

'Zum öffnen assozierter Dateien
Public Declare Function ShellExecute Lib "shell32.dll" Alias _
"ShellExecuteA" (ByVal hWnd As Long, ByVal lpOperation _
As String, ByVal lpFile As String, ByVal lpParameters _
As String, ByVal lpDirectory As String, ByVal nShowCmd _
As Long) As Long

2. Funktion die den Command-Befehl interpretiert:

Function StartDoc(ByVal DocName As String, DocCommand As String,
Optional ByVal PathName As String = "C:\")
'DocCommand = Open ; Print
Dim Ansicht As Long

'SW_SHOWNORMAL = 1
'SW_HIDE = 0

If DocCommand <> "print" Then
Ansicht = 1
End If

On Error GoTo StartDoc_Error


StartDoc = ShellExecute(frmMain.hWnd, DocCommand, DocName, "",
PathName, Ansicht)
Exit Function

StartDoc_Error:
MsgBox "Error: " & Err & " " & Error
Exit Function
End Function

3. Ausführen der Aktionen:

a) Öffnen

Private Sub lvwDatei_DblClick()
Dim DocName As String
Dim PathName As String
Dim retVal

On Error GoTo lvwDatei_DblClick_Error

10 DocName = lvwDatei.SelectedItem
20 PathName = TreeRegister.Tag & TreeRegister.SelectedItem.FullPath

30 retVal = StartDoc(DocName, "open", PathName)

On Error GoTo 0
Exit Sub

lvwDatei_DblClick_Error:

MsgBox "Fehlernr.: " & Err.Number & " (" & Err.Description & ") in
Prozedur lvwDatei_DblClick von Formular frmDocVerwaltung", , "Fehler in
Zeile: " & Erl

End Sub

b) Drucken

Private Sub mnuFilePrint_Click()
Dim DocName As String
Dim PathName As String
Dim retVal

If IsNothing(ActiveForm) Then
MsgBox "Um eine Datei zu drucken," & vbNewLine & "müssen Sie erst
eine Mandantenakte öffnen!", vbInformation
Exit Sub
End If

If IsNothing(ActiveForm.lvwDatei.SelectedItem) Then
MsgBox "Wählen Sie bitte zuerst eine Datei aus.", vbInformation
Exit Sub
End If


DocName = ActiveForm.lvwDatei.SelectedItem
PathName = ActiveForm.TreeRegister.Tag &
ActiveForm.TreeRegister.SelectedItem.FullPath

retVal = StartDoc(DocName, "print", PathName)

End Sub


Bei mir funktioniert alles einwandfrei. Die Dateien werden immer auf dem
Standarddrucker ausgedruckt. Ich muss lediglich noch eine Druckerauswahl
integrieren. Von daher sollte es bei Dir auch funktionieren.

Probiere es doch einmal aus.

Ingo R. Kirchner

unread,
Aug 14, 2006, 5:25:29 AM8/14/06
to
Hallo Gert,

nochmals vielen Dank, meine Registry Einträge stimmen wohl irgendwie
nicht, ich habe Adobe Acrobat 4.0 als Vollversion und den Reader 6.0
parallel laufen, vielleicht liegts daran. Aber das Dokument bekomme ich
ja eh gedruckt und mit PostMessage wie von dir angegeben
closeclasswindow("adobeacrobat") geht das Fenster brav zu.

Besten Dank

Ingo

Ingo R. Kirchner

unread,
Aug 14, 2006, 5:26:54 AM8/14/06
to
Hallo Ahmed, besten Dank auch, habs gelöst dank Gerts Code, drucken war
j anicht das Problem, schließen von Acrobat.

Gruß Ingo

Ahmed Martens

unread,
Aug 14, 2006, 6:17:02 AM8/14/06
to
Am Mon, 14 Aug 2006 08:18:11 +0200 schrieb Ahmed Martens:
> Bei mir funktioniert alles einwandfrei. Die Dateien werden immer auf dem
> Standarddrucker ausgedruckt. Ich muss lediglich noch eine Druckerauswahl
> integrieren. Von daher sollte es bei Dir auch funktionieren.

Also ich muss meine Antwort revidieren. Es funktioniert nicht bei
PDF-Dateien. Alle anderen werden korrekt ausgedruckt.

Eine Abhilfe wäre, das PDF-OCX im Programm zu integrieren und erst mit
AcroPDF1.LoadFile("C:\Test.PDF") diese zu laden. Danach einfach
AcroPDF1.Printwithdialog diese Datei auf den ausgewählten Drucker
auszudrucken.

Das funktioniert!

Kennt aber jemand vielleicht eine Möglichkeit, auf einen bestimmten
vorgegeben Drucker zuzugreifen bzw. diesen vorzugeben?

Ahmed Martens

unread,
Aug 14, 2006, 6:21:25 AM8/14/06
to
Hallo Ingo,

Am Mon, 14 Aug 2006 11:26:54 +0200 schrieb Ingo R. Kirchner:

> Hallo Ahmed, besten Dank auch, habs gelöst dank Gerts Code, drucken war
> j anicht das Problem, schließen von Acrobat.

kannst Du denn bestimmen auf welchen Drucker gedruckt werden soll?

Meines Erachtens wird nämlich bei den PDF's immer auf den zuletzt
verwendeten ausgedruckt. Kannst Du das vielleicht prüfen?

Ingo R. Kirchner

unread,
Aug 14, 2006, 11:58:27 AM8/14/06
to
Hallo Ahmed, das Drucken ist nicht das Problem, nochmals, ich will keine
PDF-Dokumente mit dem PDF-Drucker erstellen, sondern sie nur im
Hintergrund einfach auf Papier ausdrucken. Das funktioniert einwandfrei
mit den o.g. Parametern. Das Problem war, daß ich den Acrobat Reader,
der dabei geöffnet wird, nicht wieder schließen konnte.
Den Standarddrucker systemweit zu wechseln mache ich mit dem Code wie
angefügt, Du brauchst ein Form, eine Listbox, ein Textfeld und den
ok-Button, wenn du den Druckernamen weisst, kannst du das auch
automatisieren und wieder zurücksetzen. Im MS Office (für VBA) gibts ja
mittlerweile ein DruckerObjekt.
Wenn Du aber automatisiert PDF-Dokumente erstellen willst, dafür nehme
ich immer die dynapdf.dll, also in VBA funzt das einwandfrei.

Hier der Code, Gruß Ingo


*******************************************************
Option Explicit

'Verwendet mdlPrinterDefault
'Verwendet mdlINIDatei

Private Const LOWERLIMIT As Long = -32768
Private Const UPPERLIMIT As Long = 32767

Private Declare Function SendMessage Lib "user32" Alias "SendMessageA"
(ByVal hWnd As Long, ByVal Msg As Long, wParam As Any, lParam As Any) As
Long

Private Declare Function lstrcpy Lib "kernel32" (ByVal lpString1 As Any,
ByVal lpString2 As Any) As Long


Private Sub DefPrint_DblClick()

Dim xxnam As String
Dim PD As PRINTER_DEFAULTS
Dim retval As Long, hPrinter As Long

PD.pDatatype = 0
PD.DesiredAccess = PRINTER_ALL_ACCESS
PD.pDevMode = 0
xxnam = DefPrint.Text

retval = OpenPrinter(xxnam, hPrinter, PD)
If retval = 0 Then
MsgBox "OpenPrinter Failed!"
Else
retval = PrinterProperties(hWnd, hPrinter)
retval = ClosePrinter(hPrinter)
End If

End Sub

Private Sub Form_Load()

Dim r As Long
Dim Buffer As String, x As String

'Dieser Code füllt die Listbox mit allen verfügbaren Druckern. Der
Anwender
'kann per Doppelklick einen Drucker auswählen und zum
Standarddrucker machen.

'Get the list of available printers from WIN.INI
Buffer = Space(8192)
r = GetProfileString("PrinterPorts", vbNullString, "", Buffer,
Len(Buffer))

'Display the list of printer in the list box List1
'ParseList Me!List1, Buffer

Buffer = Trim(Buffer)

x = ParseList(Buffer)

Dim feld() As String
feld = Split(x, ";")
Dim n
For n = 0 To UBound(feld())
List1.AddItem feld(n)
Next n

'List1.List = x

x = GetProfile("win.ini", "Windows", "Device")

r = InStr(1, x, ",")
If r > 0 Then
x = Left(x, r - 1)
End If

DefPrint = x

End Sub

Private Function ParseList(ByVal Buffer As String) As String

Dim i As Integer, ZStr As String
ParseList = ""

Do While (Right(Buffer, 1) = Chr(0) Or Right(Buffer, 1) = " " Or
Right(Buffer, 1) = ";")
Buffer = Left(Buffer, Len(Buffer) - 1)
Loop

Do
i = InStr(Buffer, Chr(0))
ZStr = ""
If i > 0 Then
ZStr = Left(Buffer, i - 1)
Buffer = Mid(Buffer, i + 1)
Else
ZStr = Buffer
Buffer = ""
End If

If Len(ParseList) > 0 Then
ParseList = ParseList & ";" & ZStr
Else
ParseList = ZStr
End If
Loop While i > 0

End Function

Private Sub List1_DblClick()

Dim OSInfo As OSVERSIONINFO
Dim retValue As Integer
Dim x As String
Dim r As Long

OSInfo.dwOSVersionInfoSize = 148
OSInfo.szCSDVersion = Space$(128)
retValue = GetVersionExA(OSInfo)

If OSInfo.dwMajorVersion = 3 And OSInfo.dwMinorVersion = 51 And _
OSInfo.dwPlatformId = 2 Then
If MsgBox("Standard-Drucker ändern in " & Me!List1 & vbCrLf & _
"Sind Sie sicher ?", (vbYesNo + vbQuestion), "Win NT 3.51
Druckerwechsel") = vbYes Then
Call WinNTSetDefaultPrinter(Me!List1)
x = GetProfile("win.ini", "Windows", "Device")

r = InStr(1, x, ",")
If r > 0 Then
x = Left(x, r - 1)
End If

Me!DefPrint = x
Else
Exit Sub
End If
ElseIf OSInfo.dwMajorVersion = 4 _
And OSInfo.dwPlatformId = 1 Then
If MsgBox("Standard-Drucker ändern in " & Me!List1 & vbCrLf & _
"Sind Sie sicher ?", (vbYesNo + vbQuestion), "Win 95 / 98
Druckerwechsel") = vbYes Then
Call Win95SetDefaultPrinter(Me!List1)
x = GetProfile("win.ini", "Windows", "Device")

r = InStr(1, x, ",")
If r > 0 Then
x = Left(x, r - 1)
End If

Me!DefPrint = x
Else
Exit Sub
End If
ElseIf OSInfo.dwMajorVersion >= 4 And OSInfo.dwPlatformId = 2 Then
If MsgBox("Standard-Drucker ändern in " & Me!List1 & vbCrLf & _
"Sind Sie sicher ?", (vbYesNo + vbQuestion), "Win NT 4
Druckerwechsel") = vbYes Then
Call WinNTSetDefaultPrinter(Me!List1)
x = GetProfile("win.ini", "Windows", "Device")

r = InStr(1, x, ",")
If r > 0 Then
x = Left(x, r - 1)
End If

Me!DefPrint = x
Else
Exit Sub
End If
End If

End Sub

Private Sub SetDefaultPrinter(ByVal PrinterName As String, ByVal
DriverName As String, ByVal PrinterPort As String)

Dim DeviceLine As String
Dim r As Long
Dim l As Long
DeviceLine = PrinterName & "," & DriverName & "," & PrinterPort
' Neue Drucker Informationen im [WINDOWS] Abschnitt der WIN.INI
speichern
r = WriteProfileString("windows", "Device", DeviceLine)
' Alle Applikationen müssen die WIN.INI neu einlesen:
l = SendMessage(HWND_BROADCAST, WM_WININICHANGE, 0, "windows")

End Sub

Private Sub GetDriverAndPort(ByVal Buffer As String, DriverName As
String, PrinterPort As String)

Dim iDriver As Integer
Dim iPort As Integer
DriverName = ""
PrinterPort = ""

'Der Treibername steht am Anfang des "Komma"-terminierten Strings
iDriver = InStr(Buffer, ",")
If iDriver > 0 Then

'Treibernamen extrahieren
DriverName = Left(Buffer, iDriver - 1)

'Nach dem Treibernamen folgt der Anschluß
iPort = InStr(iDriver + 1, Buffer, ",")

If iPort > 0 Then
'Anschluß bestimmen
PrinterPort = Mid(Buffer, iDriver + 1, _
iPort - iDriver - 1)
End If
End If

End Sub

Private Sub OK_Click()

Dim r As Long
Dim x As String
x = GetProfile("win.ini", "Windows", "Device")

r = InStr(1, x, ",")
If r > 0 Then
x = Left(x, r - 1)
End If

frmGlobal.txtStatus.Text = "Standard-Drucker: " & x

Unload Me

End Sub

Private Sub Win95SetDefaultPrinter(Druckername As String)

Dim handle As Long 'Drucker Handle
Dim PrinterName As String
Dim PD As PRINTER_DEFAULTS
Dim x As Long
Dim need As Long ' benötigte Bytes
Dim pi5 As PRINTER_INFO_5 ' eigene PRINTER_INFO Struktur
Dim LastError As Long

' ausgewählten Drucker bestimmen
'PrinterName = List1.List(List1.ListIndex)
PrinterName = Druckername
' none - exit
If PrinterName = "" Then
Exit Sub
End If

' PRINTER_DEFAULTS members setzen
PD.pDatatype = 0&
PD.DesiredAccess = PRINTER_ALL_ACCESS

' Drucker Handle bestimmen
x = OpenPrinter(PrinterName, handle, PD)
' failed the open
If x = False Then
'Error Handler Code wird hier plaziert
Exit Sub
End If

' Aufruf von GetPrinter() zum Vorbereiten von (PRINTER_INFO_5)
Information
' um die Anzahl der benötigten Bytes zu bestimmen
x = GetPrinter(handle, 5, ByVal 0&, 0, need)
'GetLastError() Aufrufe schlagen hier fehl mit
' 122 - ERROR_INSUFFICIENT_BUFFER

ReDim t((need \ 4)) As Long

' zweiter administrativer Aufruf von GetPrinter
x = GetPrinter(handle, 5, t(0), need, need)
' auf Gültigkeit überprüfen
If x = False Then
'Error Handler Code wird hier plaziert
Exit Sub
End If

'Struktur schreiben um SetPrinter erfolgreich auszuführen.
' PtrCtoVbString kopiert den Inhalt des Speichers der beiden
' String Pointer des t() arrays in einen Visual Basic String.
' Die anderen 3 Elemente sind einfache DWORDS (Long Integer)
' und benötigen dementsprechend keine Konvertierung.
pi5.pPrinterName = PtrCtoVbString(t(0))
pi5.pPortName = PtrCtoVbString(t(1))
pi5.Attributes = t(2)
pi5.DeviceNotSelectedTimeout = t(3)
pi5.TransmissionRetryTimeout = t(4)

' Flag für Standarddrucker setzen
pi5.Attributes = PRINTER_ATTRIBUTE_DEFAULT

' call SetPrinter to set it
x = SetPrinter(handle, 5, pi5, 0)
' Ausführung überprüfen
If x = False Then
MsgBox "SetPrinterFailed. Error code: " & GetLastError()
Exit Sub
End If

' Handle wieder schließen
ClosePrinter (handle)

End Sub

Private Sub WinNTSetDefaultPrinter(Druckername As String)

Dim Buffer As String
Dim DeviceName As String
Dim DriverName As String
Dim PrinterPort As String
Dim PrinterName As String
Dim r As Long
'If List1.ListIndex > -1 Then
If Len(Druckername) > 0 Then

'Druckerinformationen des aktuellen Standarddruckers
'aus der WIN.INI bestimmen
Buffer = Space(1024)
' PrinterName = List1.Text
PrinterName = Druckername
r = GetProfileString("PrinterPorts", PrinterName, "", _
Buffer, Len(Buffer))

'Treibernamen und Anschluß aus Puffer parsen
GetDriverAndPort Buffer, DriverName, PrinterPort

If DriverName <> "" And PrinterPort <> "" Then
SetDefaultPrinter Druckername, DriverName, PrinterPort
End If
End If

End Sub

Private Function PtrCtoVbString(Add As Long) As String

Dim sTemp As String * 512, x As Long

x = lstrcpy(sTemp, Add)
If (InStr(1, sTemp, Chr(0)) = 0) Then
PtrCtoVbString = ""
Else
PtrCtoVbString = Left(sTemp, InStr(1, sTemp, Chr(0)) - 1)
End If

End Function


**********************************************************************

Ahmed Martens

unread,
Aug 14, 2006, 3:10:06 PM8/14/06
to
Hallo Ingo,

jetzt hast Du mich wohl falsch verstanden. Ich habe bereits PDF-Dateien.
Diese möchte ich aber per VB auf einen bestimmten Drucker ausgeben.
Leider wird aber anscheinend immer der letzte ausgewählte Drucker
genommen und nicht der Standarddrucker.

Bei allen anderen Dateien gehe ich wie folgt vor:

1. Aufruf eines CommonDialog zu Druckerauswahl (Standarddrucker wird
temporär geändert.

2. Aufruf der ShellExecute-Anweisung zum drucken.

3. Rücksetzen auf den alten Drucker.

Das funktioniert aber nicht mit PDF-Dateien. Den Drucker kann ich nur
über folgender Anweisung aufrufen: AcroPDF1.Printwithdialog
Nur dann wird ein Druckerwechsel auch angenommen und wieder
standardmäßig gespeichert.

Dieses Vorgehen ist bei einer Datei ja noch akzeptabel. Möchte ich aber
mehrere PDF's ausdrucken, so ist es für den Anwender nervig für jede
Datei den Druckerdialog zu nehmen.

Meine Frage nun an alle. Gibt es eine Möglichkeit den Druck eines
PDF-Dokumentes auf einen bestimmten Drucker auszudrucken, ohne das dafür
der Druckerdialog von Acrobat genommen werden muss?

Vielen Dank im voraus für Eure Hilfe.

Ingo Moch

unread,
Aug 14, 2006, 4:53:15 PM8/14/06
to

"Ingo R. Kirchner" schrieb:

> also ich kenne das dritte Gebot leider nicht,

Applemans drittest Gebot besagt, bei API-
Funktionen immer die Rueckgabewerte zu pruefen.


> Bei mir funktioniert der von dir gelieferte
> Code nicht, benutze zwar den Reader 6.0 aber
> das dürfte ja kein Unterschied machen.
> nresult = 5 und damit konnte Dokument nicht
> ausdrucken, es tut sich auch gar nichts.

Hast Du mal geschaut, was der Code 5 bedeutet?

http://msdn.microsoft.com/library/en-us/shellcc/platform/shell/reference/functions/shellexecute.asp

5 = SE_ERR_ACCESSDENIED = Es sind nicht genug
Rechte für den Zugriff vorhanden

> Wenn alles so klar ist warum sagst du es mir
> dann nicht einfach

Du laesste einen im Dunkeln stochern! Von daher
kann ich nur raten ... und wie Du an der gefunden
Loesung siehst, habe ich richtig geraten, was
durch eine konkrete Antwort von Dir auf die Frage
mit deutlich weniger Aufwand verifizierbar waere.

> statt mich auf irgednwelche Gebote zu verweisen.

Wie Du oben sieht, war es kein schlechter Hinweis.

> Also wenn ich hier schon mal poste, dann hab
> ich schon alles mögliche probiert und suche
> hilfreiche Unterstützung, nicht Egomania.

Entschudige bitte ... Du hat eigentlich immer nur
mehr oder weniger umschrieben "es geht nicht"
geschrieben und nicht auf konkere Fragen
geantwortet. Dass Du neben dem eigentlichen Problem
(dem abschiessen der Anwendung) noch ein
Rechteproblem hast, kann keiner ahnen. Zu einer
guten Hilfe gehoert auch eine gute Problem-
beschreibung durch den Fragenden.

Wenn Du Hilfe nicht als solche erkennst, ist das
dein Problem.

[F'Up2 poster gesetzt]

Tschau
Ingo


Frank Heindörfer

unread,
Aug 15, 2006, 1:54:14 AM8/15/06
to
Hallo Ingo,

verwende doch DDE. Damit lässt sich eine PDF-Datei mit Hilfe der Adobe
Reader im Hintergrund ausdrucken und der Adobe Reader kann per
DDE-Kommando (AppExit) auch wieder geschlossen werden (ohne einen
Prozess abzuschießen). Beispiele dazu finden sich genug im Netz.

Tschüss Frank

0 new messages