ABOUT Visual Basic Programmieren Programmierung Download Downloads Tips & Tricks Tipps & Tricks Know-How Praxis VB VBA Visual Basic for Applications VBS VBScript Scripting Windows ActiveX COM OLE API ComputerPC Microsoft Office Microsoft Office 97 Office 2000 Access Word Winword Excel Outlook Addins ASP Active Server Pages COMAddIns ActiveX-Controls OCX UserControl UserDocument Komponenten DLL EXE
Diese Seite wurde zuletzt aktualisiert am 30.06.2000

Diese Seite wurde zuletzt aktualisiert am 30.06.2000
Aktuell im ABOUT Visual Basic-MagazinGrundlagenwissen und TechnologienKnow How, Tipps und Tricks rund um Visual BasicActiveX-Komponenten, Controls, Klassen und mehr...AddIns für die Visual Basic-IDE und die VBA-IDEVBA-Programmierung in MS-Office und anderen AnwendungenScripting-Praxis für IE, Windows Scripting Host und das Scripting-ControlTools, Komponenten und Dienstleistungen des MarktesRessourcen für Programmierer (Bücher, Job-Börse)Dies&Das...

Themen und Stichwörter im ABOUT Visual Basic-Magazin
Code, Beispiele, Komponenten, Tools im Überblick, Shareware, Freeware
Ihre Service-Seite, Termine, Job-Börse
Melden Sie sich an, um in den vollen Genuss des ABOUT Visual Basic-Magazins zu kommen!
Informationen zum ABOUT Visual Basic-Magazin, Kontakt und Impressum

Zurück...

Zurück...

(-hg) mailto:hg_vbsprinterobj@aboutvb.de

Eigentlich ist es ja eine Schande. Da gibt es zum Beispiel das schöne FileSystemObject - und eine Datei- oder Verzeichnisliste können Sie nur auf Umwegen und nur mit minimalster gestalterischer Freiheit ausdrucken: Liste in Datei schreiben, Datei über Shell-Funktionen auf dem Standard-Drucker ausdrucken. Wie wäre es mit einem Printer-Objekt fürs Windows-Scripting, das Ihnen die Möglichkeit bietet, Texte und sogar Grafiken in nahezu beliebiger Gestaltung zu drucken?

Nun, ich kann und will Ihnen nicht zu viel versprechen, jedenfalls nicht mehr, als... ja, als das in Visual Basic eingebaute Printer-Objekt zu leisten imstande ist. Aber das ist schon eine ganze Menge, weitaus mehr, als Sie wahrscheinlich mit den Möglichkeiten von VBScript im Windows Scripting Host überhaupt ausnutzen werden können.

Leider geht es nicht, das VB-Printer-Objekt per CreateObject direkt zu instanzieren und zu verwenden. Es ist kein echtes COM- bzw. ActiveX-Objekt. Innerhalb einer Visual Basic-Anwendung steht das Printer-Objekt jedoch jederzeit frei zur Verfügung. Was also fehlt, ist also eine solche VB-Anwendung, genauer gesagt, eine mit VB erstellte ActiveX-Komponente, der das Printer-Objekt sowohl instanziert und für den Zugriff per Scripting zur Verfügung stellt, als auch dessen Eigenheiten mit Hilfe von ein paar Hilfsfunktionen umschifft.

Die sozusagen eigenartigste Eigenheit des Printer-Objekts steckt hinter seiner wohl am häufigsten benötigten und verwendeten Methode, der Print-Methode in der "klassischen" Basic-Syntax. Ohne "Print" kann kein Text ausgegeben werden - und diese Methode können Sie von der Scripting-Seite aus leider nicht benutzen. Sie könnten lediglich Linien, Kästen und Kreise aufs Papier malen lassen und Bilder ausgeben.

Halt, nein, letzteres ist nicht richtig - in Punkto Bilder tritt die zweite Eigenheit des Printer-Objekts zutage. Was allerdings so auch wieder nicht stimmt. Das Printer-Objekt kann nichts dafür, dass es nur Bilder verarbeiten kann, die ihm als StdPicture-Objekt, einem Standard-COM-/OLE-Objekt übergeben werden. Hier liegt das Problem bei VBScript bzw. dem Windows Scripting Host - diese können leider nicht mit dem StdPicture-Objekt richtig umgehen (Beim StdFont-Objekt scheinen da keine Stolpersteine im Weg zu liegen). Es mag sein, dass es irgendwelche Hintertüren gibt, die aber die üblichen Scripting-Horizonte übersteigen würden. Eine zusätzliche Aufgabe für den Printer-ActiveX-Server wäre also, dafür zu sorgen, dass Sie Bilder laden und nach Ihren Layoutvorstellungen über das Printer-Objekt ausgeben können.

Die Hauptaufgabe ist schnell erledigt. In einer Eigenschaft wird die VB-Printers-Sammlung zur Verfügung gestellt, über die alle installierten Drucker ermittelt werden können. In einer zweiten Eigenschaft wird das Printer-Objekt selbst bereitgestellt. Sie können über diese Objekt-Referenz nahezu alles machen, was Sie mit dem Printer-Objekt in VB machen können (soweit der Sprachumfang von VBScript dies ermöglicht) - schließlich ist es ja das originale VB-Printer-Objekt.

Public Property Get Printer() As Object
  Set Printer = VB.Printer
End Property

Public Property Get Printers() As Object
  Set Printers = VB.Printers
End Property

Lediglich zwei Methoden bereiten Probleme. Die eine, wie bereits gesagt, ist die Print-Methode. Die Schwierigkeiten damit rühren wahrscheinlich daher, dass diese gar keine Methode im eigentlichen Sinne ist. Schon der VB-Objektkatalog verschweigt deren Existenz. Die Print-Methode, richtiger gesagt, die Print-Anweisung, ist ein Relikt aus der Basic-Historie. Mit ihrer eigenwillig anmutenden Syntax wissen moderne Script-Sprachen-Konzepte nichts mehr anzufangen. Eine Code-Zeile mit einem abschließenden Komma oder Semikolon ist hier ein Unding - für routinierte Print-Verwender dagegen das Selbstverständlichste von der Welt. Für den Fall, dass Sie diese spezielle Syntax nicht kennen sollten: Ein Komma gibt an, dass das nächste zu druckende Element an der nächsten (eingebauten) Tabulatorstelle ausgegeben wird, ein Semikolon gibt an, dass es unmittelbar und lückenlos auf das vorhergehende Element folgend ausgegeben wird. Kommata und Semikola können sowohl zwischen den zu druckenden Elementen als auch am Zeilenende stehen. Stehen sie am Zeilenende, wird damit signalisiert, dass die nächste Print-Anweisung an dieser Stelle dem Zeichen entsprechend weitermachen soll.

Die Code-Zeile

Print "ABC"; "DEF"; "GHI", "123"

sähe im Ausdruck etwa so aus:

        ABCDEFGHI    123

Und die Anweisungsfolge

Print "Erste Zeile"

Print "Zweite Zeile",

Print "Immer noch zweite Zeile"

ergäbe:

        Erste Zeile
        Zweite Zeile     Immer noch zweite Zeile

Schließlich resultiert aus den folgenden Anweisungen

Print "A";

Print "B";

Print "C"

im Druck:

        ABC

Der Printer-Server muss daher selbst eine in etwa funktional gleichwertige Anweisung zur Verfügung stellen. Auf ein zu druckendes Element je Print-Aufruf reduziert, ist die Umsetzung recht einfach: Übergabe des zu druckenden Textelements im ersten Parameter, und in einem zweiten Parameter erfolgt die Übergabe einer Kennung, die quasi ein Komma oder ein Semikolon signalisiert, oder keines von beiden. Da Print in Basic ein strikt reserviertes Schlüsselwort ist, nennen wir die Ersatzmethode PrintText. Die Print-gemäße Gewohnheit, mehrere Elemente in einer Anweisungszeile übergeben zu können, müssen Sie jedoch ablegen - PrintText ist für jedes Element separat aufzurufen. Die Funktionalität ist jedoch entsprechend der übergebenen Kennung gewährleistet.

Public Sub PrintText(Text As Variant, Optional LineMode _
 As Variant)
  On Error Resume Next
  If IsMissing(LineMode) Then
    VB.Printer.Print Text
  Else
    Select Case CInt(LineMode)
      Case 0
        VB.Printer.Print Text
      Case 1 ' Semikolon
        VB.Printer.Print Text;
      Case 2 ' Komma
        VB.Printer.Print Text,
    End Select
  End If
  If Err.Number Then
    Err.Raise Err.Number, Err.Source, Err.Description, _
     Err.HelpFile, Err.HelpContext
  End If
End Sub

Die zweite angesprochene Schwierigkeit, die die Bild-Objekte betrifft, kommt bei der PaintPicture-Methode zum Tragen. Diese Methode würde als COM-konforme Methode klaglos funktionieren, wenn nicht die Scripting-Umgebung Probleme mit dem StdPicture-Objekt hätte. Ein solches Objekt kann offensichtlich nicht die Grenze zwischen dem VB-ActiveX-Server und der Scripting-Umgebung überschreiten - es tritt unweigerlich ein Automatisierungsfehler auf.

Wegen der vielen optionalen Parameter der PaintPicture-Methode, die jedoch beim Printer-Objekt keine leeren Variants annehmen können, ist die Umsetzung nicht mit einem simplen Durchreiche-Aufruf erledigt. Es muss vielmehr bei jedem einzelnen optionalen Parameter geprüft werden, ob ein Wert übergeben wurde. Entweder wird dieser oder, falls er fehlen sollte, ausdrücklich der Standardwert an den eigentlichen PaintPicture-Aufruf des VB-Print-Objekts übergeben. Da Scripting-Gepflogenheiten gemäß die übergebenen optionalen Parameter vom Datentyp Variant sind, kann die Übergabe eines Wertes leicht mit der VB-Funktion IsMissing geprüft werden.

Public Sub PaintPicture(Picture As Variant, Left1 As Variant, _
 Top1 As Variant, Optional Width1 As Variant, Optional Height1 _
 As Variant, Optional Left2 As Variant, Optional Top2 As Variant, _
 Optional Width2 As Variant, Optional Height2 As Variant, _
 Optional Opcode As Variant)
  Dim nWidth1 As Single
  Dim nHeight1 As Single
  Dim nLeft2 As Single
  Dim nTop2 As Single
  Dim nWidth2 As Single
  Dim nHeight2 As Single
  Dim nOpcode As Long
  Dim nPicture As StdPicture
  
  On Error GoTo PaintPicture_Error
  Set nPicture = Picture.Picture
  With VB.Printer
    If IsMissing(Width1) Then
      nWidth1 = .ScaleX(nPicture.Width, vbHimetric, .ScaleMode)
    Else
      nWidth1 = CSng(Width1)
    End If
    If IsMissing(Height1) Then
      nHeight1 = .ScaleX(nPicture.Height, vbHimetric, .ScaleMode)
    Else
      nHeight1 = CSng(Height1)
    End If
    If IsMissing(Left2) Then
      nLeft2 = 0
    Else
      nLeft2 = CSng(Left2)
    End If
    If IsMissing(Top2) Then
      nTop2 = 0
    Else
      nTop2 = CSng(Top2)
    End If
    If IsMissing(Width2) Then
      nWidth2 = .ScaleX(nPicture.Width, vbHimetric, .ScaleMode)
    Else
      nWidth2 = CSng(Width2)
    End If
    If IsMissing(Height2) Then
      nHeight2 = .ScaleX(nPicture.Width, vbHimetric, .ScaleMode)
    Else
      nHeight2 = CSng(Height2)
    End If
    If IsMissing(Opcode) Then
      nOpcode = vbSrcCopy
    Else
      nOpcode = CLng(Opcode)
    End If
    .PaintPicture nPicture, CSng(Left1), CSng(Top1), nWidth1, _
     nHeight1, nLeft2, nTop2, nWidth2, nHeight2, nOpcode
  End With
  Exit Sub
  
PaintPicture_Error:
  Err.Raise Err.Number, Err.Source, Err.Description, _
   Err.HelpFile, Err.HelpContext
End Sub

Sie sehen, dass auch hier von außen ein Picture-Objekt als Parameter übergeben werden soll. Doch wie verträgt sich dies meiner Aussage, dass das doch gar nicht ginge? Es verträgt sich, denn hier wird nicht das VB-bekannte, hier problematische StdPicture-Objekt übergeben, sondern ein eigenes, extra in diesem ActiveX-Server implementiertes Picture-Objekt - die Klasse avbPicture.

Deren Aufgabe ist ebenfalls nicht allzu umfangreich. Sie bildet die drei für Scripting-Zwecke wichtigen Eigenschaften des intern in der Objektvariablen mPicture verwalteten Originals eins zu eins ab - Height, Width und Type. Da Type wieder ein VB-Schlüsselwort ist, wird die Eigenschaft hier in PicType umbenannt. Beachten sie, dass die Eigenschaften Height und Width Werte in der Maßeinheit Himetric zurückgeben, während die Standardeinstellung des Printer-Objekts TWIPS ist. Die Umrechnung können Sie jedoch auf einfache Weise die ScaleX- bzw. ScaleY-Methode des Printer-Objekts vornehmen lassen. Eine Instanz dieser avbPicture-Klasse muss im Script mit CreateObject angelegt werden und kann nun ohne Fehlerauslösung an die PaintPicture-Methode des ActiveX-Servers übergeben werden, wo das eigentliche StdPicture-Objekt weitergereicht wird.

Private mPicture As Picture

Public Property Get Height() As Variant
  Height = mPicture.Height
End Property

Public Property Get PicType() As Variant
  PicType = mPicture.Type
End Property

Public Property Get Width() As Variant
  Width = mPicture.Width
End Property

Public Property Get Picture() As Object
  Set Picture = mPicture
End Property

Da ein leeres Picture-Objekt wertlos ist und VBScript bzw. der Scripting-Host nicht über die in VB vorhandenen Anweisungen LoadPicture und SavePicture verfügen, können Sie über die Methode LoadFromFile eine Bild- oder Grafik-Datei hineinladen. Mögliche Dateiformate sind: BMP, JPG, GIF, ICO, CUR und WMF. Wenn Sie wollen, können Sie eine geladene Bilddatei über die Methode SaveToFile unter dem gleichen oder unter einem neuen Dateinamen speichern. Eine Konvertierung des Bildformats kann das dahinterstehende StdPicture-Objekt jedoch nicht vornehmen - Sie sollten also die entsprechende Dateierweiterung in jedem Falle beibehalten.

Public Sub LoadFromFile(FileName As String)
  On Error Resume Next
  Set mPicture = LoadPicture(FileName)
  If Err.Number Then
    Err.Raise Err.Number, Err.Source, Err.Description, _
     Err.HelpFile, Err.HelpContext
  End If
End Sub

Public Sub SaveToFile(FileName As String)
  On Error Resume Next
  SavePicture mPicture, FileName
  If Err.Number Then
    Err.Raise Err.Number, Err.Source, Err.Description, _
     Err.HelpFile, Err.HelpContext
  End If
End Sub

Im Windows Scripting Host sähe die Verwendung der beiden Objekte etwa so aus:

Dim PrinterObj
Dim Printer
Dim Picture

Set PrinterObj = CreateObject("avbScriptPrinter.PrinterObj")
Set Printer = PrinterObj.Printer
Set Picture = CreateObject("avbScriptPrinter.avbPicture")
Picture.LoadFromFile "c:\windows\hlpbell.gif"

With Printer
  .ScaleMode = 7 ' Zentimeter
  .CurrentX = 5
  .CurrentY = 10
  PrinterObj.PrintText "Hallo!"
  .CurrentX = 5
  PrinterObj.PrintText "Ist da jemand?"
  PrinterObj.PaintPicture Picture, 7, 15
  .EndDoc
End With

Wie Sie mit dem nun zur Verfügung stehenden, bei Visual Basic ausgeliehenen Printer-Objekt in Ihren Scripten umgehen, ist ein Thema für sich. In Anbetracht der sich auftuenden Möglichkeiten, aber auch der sich auftuenden Fallgruben, könnte man ganze Bücher darüber schreiben. Sie finden jedoch in nahezu jedem VB-Programmierbuch mehr oder weniger umfangreiche Kapitel zu diesem Thema. Die Methoden und Eigenschaften des VB-Printerobjekts finden Sie in der VB-Dokumentation beschrieben - entweder auf Ihren mit VB oder VS gelieferten MSDN-CDs oder in der ONLINE-MSDIN-Library - VB Printer-ObjectOnline-MSDN-Library (leider nur englischsprachig).


Projekt avbScriptPrinter (scrprint.zip - ca. 3,2 KB)

Setup ActiveX-EXE (ohne VB 6-Runtime!) (scrprnts.zip - ca. 271 KB)



KnowHow-Übersicht

Zum Seitenanfang

Copyright © 1999 - 2023 Harald M. Genauck, ip-pro gmbh  /  Impressum

Zum Seitenanfang

Zurück...

Zurück...