SO WIRD'S GEMACHT: Drucken mit benutzerdefinierten Seitengrößen unter Windows NT und Windows 2000

Dieser Artikel ist eine Übersetzung des folgenden englischsprachigen Artikels der Microsoft Knowledge Base:
282474 HOWTO: Print Using Custom Page Sizes on Windows NT and Windows 2000

Zusammenfassung

Microsoft Windows 95, Windows 98 und Windows Millennium Edition (Me) sind bei angepassten, benutzerdefinierten Seitengrößen flexibel. Bei Systemen, auf denen Windows NT und Windows 2000 ausgeführt wird, müssen jedoch alle Seitengrößen als Formular definiert werden, bevor sie verwendet werden können. In diesem Artikel wird erläutert, wie Sie benutzerdefinierte Seitengrößen in Windows NT und Windows 2000 drucken. Außerdem wird mithilfe eines Codebeispiels gezeigt, wie Sie benutzerdefinierte Formulare hinzufügen, auswählen und löschen.

Der Artikel enthält folgende Abschnitte:

Weitere Informationen

DEVMODE-Mitglieder für das Definieren oder Auswählen der Seitengröße

Druckertreiber speichern ihre Standardeinstellungen in einer so genannten DEVMODE-Struktur. Wenn Sie eine Seitengröße definieren oder auswählen, können vier Mitglieder dieser Struktur beteiligt sein:

  • dmPaperSize
  • dmPaperLength
  • dmPaperWidth
  • dmFormName
Die Mitglieder dmPaperLength und dmPaperWidth enthalten Werte für alle Betriebssysteme; sie können jedoch nur auf Systemen, auf denen Windows 95, Windows 98 oder Windows Me ausgeführt wird, zum Auswählen bzw. Definieren einer Größe verwendet werden. Das Mitglied dmFormName ist nur auf Systemen unter Windows NT oder Windows 2000 gültig. Das Mitglied dmPaperSize kann auf allen Windows-Betriebssystemen mit 32 Bit verwendet werden, solange der ihm zugewiesene Wert einer Größe bzw. einem Formular entspricht, die/der auf dem System definiert ist.

Sie können also auf Systemen mit Windows 95, Windows 98 oder Windows Me benutzerdefinierte Seitengrößen nach der Höhe (Länge) und Breite oder nach einer vordefinierten Papiergröße definieren. Windows NT- oder Windows 2000-basierte Systeme verwenden nur definierte Formulare für Seitengrößen, die Sie auf folgende Weise auswählen können: Legen Sie dmFormName fest, oder weisen Sie dmPaperSize einen gültigen "konstanten" Wert zu.

Um unter Windows NT oder Windows 2000 eine bestimmte Papiergröße zu verwenden, müssen Sie ein entsprechendes Formular definieren. Das Visual Basic-Objekt Printer besitzt die Eigenschaften PageSize , Height und Width, welche die Mitglieder dmPaperSize, dmPaperLength und dmPaperWidth des DEVMODE angeben. Das Objekt Printer bietet jedoch weder eine Möglichkeit, ein Formular nach Namen auszuwählen, noch eine Methode, um ein benutzerdefiniertes Formulars zur Laufzeit hinzuzufügen. Zum Erstellen eines benutzerdefinierten Formulars und/oder Auswählen eines Formulars nach Namen muss die Win32-API (Application Programming Interface) verwendet werden.

Auswählen eines Formulars mithilfe von Programmcode

In diesem Artikel wird der grundlegende Prozess EnumForms verwendet, um alle vom aktuellen Drucker unterstützten Formulare aufzulisten und um die Höhe und Breite jedes Formulars zu überprüfen. Wird die angegebene Größe gefunden, so wird diese ausgewählt. Wird sie nicht gefunden, fügt der Code das Formular hinzu und wählt dieses dann aus.

Es gibt drei Möglichkeiten, um ein Formular mittels Programmcode auszuwählen:
  • Rufen Sie die DEVMODE-Struktur des Druckers ab, legen Sie das Mitglied dmFormName fest, und verwenden Sie die Funktion ResetDC, um dieses Formular als aktuelles Formular für den Gerätekontext (Device Context, DC) des Druckers festzulegen. Die Auswahl dieses Formulars für den Geräteprozess gilt nur für den Aufrufprozess, und die Standardeinstellung des Treibers wird nicht geändert. Hierfür sind keine besonderen Berechtigungen erforderlich. Diese Methode wird für Anwendungen bevorzugt, die die Einstellungen eines Druckers ändern.
  • Rufen Sie die Funktion SetForm auf, um das Standardformular für den Druckertreiber zu ändern. Diese Methode erfordert vollständige Zugriffsberechtigungen auf den Treiber. Wird das Standardformular geändert, wirkt sich dieses auf alle Anwendungen aus, die diesen Drucker zum Drucken verwenden. Handelt es sich um einen Netzwerkdrucker, verfügen die meisten Benutzer nicht über die nötigen Berechtigungen für diesen Aufruf.
  • Weisen Sie Printer.PageSize den systemdefinierten Wert für das benutzerdefinierte Formular zu.
Der Beispielcode in diesem Artikel veranschaulicht lediglich die erste der genannten Methoden; der Aufruf von SetForm oder die Wertzuweisung zu Printer.PageSize werden nicht gezeigt. Das Beispiel übernimmt den vom System zugewiesenen Wert des neuen benutzerdefinierten Formulars, indem es den Wert seiner Ordnungsposition in der Liste zurückgibt, die von EnumForms zurückgegeben wird. Beachten Sie, dass dies nur bei benutzerdefinierten Formularen möglich ist. Vordefinierte Formulare besitzen ihnen zugewiesene konstante Werte, die nicht ihrer Ordnungsposition in der Liste entsprechen.

Wenn Sie die Funktion AddForm verwenden, um ein benutzerdefiniertes Formular hinzuzufügen, erhält das Formular eine eigene Nummer (falls verfügbar), die dann für alle Drucker, die das Formular verwenden, konsistent bleibt. In diesem Fall wird das Formular definiert und erhält einen "konstanten" Wert für das aktuelle System. Sie können diesen Wert dann Printer.PageSize zuweisen, um ihn auszuwählen. Da die Nummernzuweisung jedoch nur eins über der Anzahl der Formulare liegt, die für den aktuellen Drucker beim Hinzufügen des Formulars aufgelistet wurde, steht die Nummer möglicherweise nicht zur Verfügung, da sie bereits von einem vordefinierten Formular verwendet wird. Sie sollten diesen Wert deshalb nicht zum Auswählen eines Formulars verwenden; er wird in diesem Beispiel auch nicht erläutert. Wenn Sie diese Nummernzuweisung verwenden und der entsprechende Wert nicht verfügbar ist, wird entweder das falsche Formular ausgewählt oder Laufzeitfehler 380 ausgelöst: "Ungültiger Eigenschaftswert."

Formularquellen und Formularfunktionen

Die meisten Formulare werden vom Betriebssystem definiert und stehen allen lokalen Druckern zur Verfügung. Formulare für Netzwerkdrucker werden jedoch auf dem Druckserver definiert. Einige Formulare können speziell für einen bestimmten Druckertreiber definiert sein und ausschließlich in der Liste dieses Treibers angezeigt werden. Eine weitere Quelle für Formulare sind angepasste bzw. benutzerdefinierte Formulare, die manuell oder mittels Code erstellt werden können und allen lokalen Drucker im System zur Verfügung stehen. Sowohl druckerspezifische als auch benutzerdefinierte Formulare werden in der Registrierung gespeichert.

Das Beispiel in diesem Artikel verwendet einige Funktionsaufrufe, die sich auf Formulare beziehen. Die wichtigsten Funktionen lassen sich wie folgt zusammenfassen:

EnumFormsGibt Informationen über alle Formulare zurück, die für den aktuellen Drucker unterstützt werden.
AddFormFügt ein benutzerdefiniertes Formular zum System hinzu. Die Daten in diesem Formular werden in der Registrierung gespeichert. Benutzerdefinierte Formulare stehen somit allen Druckern zu Verfügung, nicht nur dem Drucker, der beim Hinzufügen des Formulars aktuell war. Der numerische Wert, den das System diesem Formular zuweist, liegt eine Nummer höher als die Anzahl der Formulare, die EnumForms für den aktuellen Drucker zurückgibt. Sie müssen über vollständige Rechte für den Treiber verfügen, um diese Funktion aufrufen zu können. Wenn Sie ein Formular nicht manuell hinzufügen können, schlägt auch dieser Funktionsaufruf fehl. Aus diesem Grund können Sie diese Funktion im Allgemeinen nicht auf Netzwerkdruckern verwenden.
DeleteFormLöscht ein benutzerdefiniertes Formular. Mit dieser Funktion werden jedoch keine vom Betriebssystem definierten Standardformulare gelöscht. Bei einem entsprechenden Versuch wird Fehlercode 87 zurückgegeben. Diese Funktion erfordert dieselben Rechte wie AddForm .


Obwohl die folgenden Funktionen im Beispiel nicht verwendet werden, beinhaltet das Beispiel die Deklarationen für diese Funktionen:

GetFormRuft Informationen zu einem bestimmten Formular ab.
SetFormLegt die Standardformularinformationen für den angegebenen Drucker fest. Für diese Funktion sind vollständige Rechte erforderlich; dies gilt grundsätzlich für das Ändern von Druckertreibereinstellungen.


Es sollte darauf hingewiesen werden, dass für einige dieser Funktionen voller Zugriff auf den Drucker erforderlich ist. Aus diesem Grund funktionieren die Funktionen SetForm, AddForm und DeleteForm nahezu niemals auf Druckern, die als "Netzwerkdrucker" installiert sind. Dies liegt daran, dass die Treiber für Netzwerkdrucker nicht lokal installiert werden, sondern sich auf dem Druckserver befinden, und Ihr Benutzerkonto höchstwahrscheinlich nicht über Administratorrechte für den Druckserver verfügt. Bei Systemen unter Windows 95, Windows 98 oder Windows Me ist dies anders - dort sind alle Druckertreiber (auch für Netzwerkdrucker) stets lokal installiert. Sie können Netzwerkdrucker jedoch als lokale Drucker unter Windows NT oder Windows 2000 installieren und den Anschluss auf die Druckerwarteschlage festlegen. Sie können dann mithilfe dieser Funktionen Änderungen vornehmen, ohne andere Benutzer zu beeinflussen, die den Drucker ebenfalls verwenden.

Schritte zum Hinzufügen eines lokalen Druckertreibers für einen Netzwerkdrucker

  1. Zeigen Sie im Menü Start auf Einstellungen, und klicken Sie dann auf Drucker. Doppelklicken Sie auf Neuer Drucker, um den Assistenten für die Druckerinstallation zu starten.
  2. Klicken Sie auf Lokaler Drucker oder Arbeitsplatz und NICHT auf Netzwerkdrucker, sobald Sie dazu aufgefordert werden. Sie werden zwar eine Verbindung zu einem Netzwerkdrucker herstellen, sollten aber einen Treiber von Ihrem Arbeitsplatz verwenden. Klicken Sie auf Weiter, um fortzufahren.
  3. Klicken Sie in Windows NT auf Hinzufügen. Klicken Sie in Windows 2000 auf Einen neuen Anschluss erstellen.
  4. Klicken Sie im Dropdown-Listenfeld auf den Eintrag für einen lokalen Anschluss. Klicken Sie in Windows NT auf den Eintrag für einen neuen Anschluss. Klicken Sie in Windows 2000 auf Weiter, und Sie werden aufgefordert, einen Anschlussnamen einzugeben.
  5. Geben Sie den Standort des Druckers im Netzwerk ein. Beispiel:
    \\Druckserver\Druckername,
    wobei Sie den genauen Pfadnamen zum Drucker verwenden.
  6. Klicken Sie auf OK, und beenden Sie den Assistenten.
Wenn Sie die Druckereigenschaften für den aktiven Drucker ändern, wirkt sich dies weiterhin auf alle Anwendungen aus, die diesen Drucker verwenden, jedoch gilt dies nur für das lokale System.

WICHTIG Wenn Sie benutzerdefinierte Seitengrößen verwenden, ist das Verhalten von Laser- oder Tintenstrahldruckern und Nadel- oder Anschlagdruckern unterschiedlich. Kein Drucker akzeptiert eine Seitengröße, deren Breite über seine physischen Möglichkeiten hinausgeht. Allerdings können Drucker, die Endlospapier verwenden, bei den Seitengrößen flexibel sein, da sie zeilenorientiert vorgehen. Laser- und Tintenstrahldrucker drucken jeweils eine Seite. Wenn Sie also über einen Nadeldrucker drucken (der Endlospapier verwendet), können Sie die Seitenlänge während eines Seitenvorschubs mühelos erkennen, da der Drucker an die Stelle springt, an der er den Anfang der nächsten Seite vermutet, unabhängig von der tatsächlichen Größe des verwendeten Papiers. Bei Laser- und Tintenstrahldruckern wird, unabhängig von der erwarteten Seitengröße, bei einem Seitenvorschub stets eine ganze Seite vorgeschoben. Bei den meisten Laserdruckern wird zudem meist die Aufforderung angezeigt, den entsprechenden Papierschacht zu befüllen, wenn Sie den Drucker auffordern, auf einer benutzerdefinierten Seite zu drucken.

Schritt-für-Schritt-Beispiel

  1. Festlegen eines lokalen Druckers als Standarddrucker. Führen Sie dazu die folgenden Schritte aus:
    1. Zeigen Sie im Menü Start auf Einstellungen, und klicken Sie dann auf Drucker.
    2. Klicken Sie mit der rechten Maustaste auf das Symbol für einen lokalen Drucker, und klicken Sie dann auf Als Standard definieren.
  2. Starten Sie in Visual Basic ein neues Standard-EXE-Projekt. Form1 wird standardmäßig erstellt.
  3. Fügen Sie Form1 drei Befehlsschaltflächen und ein Listenfeld-Steuerelement hinzu.
  4. Fügen Sie den folgenden Code in das Modul von Form1 ein:
    Option Explicit

    Private Sub Command1_Click()
    Dim FormName As String

    FormName = "MeinBenutzerdefiniertesFormular" ' Verwenden eines speziellen, benutzerdefinierten Formulars.
    UseForm FormName
    End Sub

    Private Sub Command2_Click()
    Dim FormName As String

    ' Abrufen des Formularnamens aus dem Listenfeld.
    On Error GoTo ListBoxERR ' Trap für keine Auswahl.
    FormName = Mid(List1.Text, 1, InStr(1, List1.Text, " -") - 1)
    On Error GoTo 0 ' Deaktivieren der Fehlerbehebung.

    UseForm FormName

    Exit Sub
    ListBoxERR:
    MsgBox "Wählen Sie einen Drucker aus dem Listenfeld aus, bevor Sie diese Option verwenden.", _
    vbExclamation
    End Sub

    Private Sub Command3_Click()
    Dim RetVal As Long
    Dim PrinterHandle As Long ' Handle an Drucker
    Dim PrinterName As String
    Dim FormName As String
    Dim Continue As Long

    ' Löschen des im Listenfeld ausgewählten Formulars.
    PrinterName = Printer.DeviceName ' Aktueller Drucker
    If OpenPrinter(PrinterName, PrinterHandle, 0&) Then

    On Error GoTo ListBoxERR ' Trap für keine Auswahl.
    FormName = Mid(List1.Text, 1, InStr(1, List1.Text, " -") - 1)
    On Error GoTo 0 ' Deaktivieren der Fehlerbehebung.

    Continue = MsgBox("Sind Sie sicher, dass Sie " & _
    FormName & " dauerhaft von " & PrinterName & " entfernen möchten?", vbYesNo)
    If Continue = vbYes Then
    RetVal = DeleteForm(PrinterHandle, FormName & Chr(0))
    If RetVal <> 0 Then ' Löschen des Formulars erfolgreich.
    List1.Clear ' Anzeigen des Löschens im Listenfeld.
    Form_Load ' Neuerstellen der Liste.
    MsgBox FormName & " gelöscht!", vbInformation, "Erfolg!"
    Else
    MsgBox FormName & " nicht gelöscht!" & vbCrLf & vbCrLf & _
    "Fehlercode: " & Err.LastDllError, vbInformation, "Fehler!"
    End If
    End If
    ClosePrinter (PrinterHandle)
    End If

    Exit Sub
    ListBoxERR:
    MsgBox "Wählen Sie einen Drucker aus dem Listenfeld aus, bevor Sie diese Option verwenden.", _
    vbExclamation
    ClosePrinter (PrinterHandle)
    End Sub

    Private Sub Form_Load()
    Dim NumForms As Long, I As Long
    Dim FI1 As FORM_INFO_1
    Dim aFI1() As FORM_INFO_1 ' Arbeitsdatenfeld FI1
    Dim Temp() As Byte ' Temporäres FI1-Datenfeld
    Dim BytesNeeded As Long
    Dim PrinterName As String ' Aktueller Drucker
    Dim PrinterHandle As Long ' Handle an Drucker
    Dim FormItem As String ' Für Listenfeld
    Dim RetVal As Long
    Dim FormSize As SIZEL ' Größe des gewünschten Formulars

    PrinterName = Printer.DeviceName ' Aktueller Drucker
    If OpenPrinter(PrinterName, PrinterHandle, 0&) Then
    With FormSize ' Gewünschte Seitengröße
    .cx = 214000
    .cy = 216000
    End With
    ReDim aFI1(1)
    RetVal = EnumForms(PrinterHandle, 1, aFI1(0), 0&, BytesNeeded, _
    NumForms)
    ReDim Temp(BytesNeeded)
    ReDim aFI1(BytesNeeded / Len(FI1))
    RetVal = EnumForms(PrinterHandle, 1, Temp(0), BytesNeeded, _
    BytesNeeded, NumForms)
    Call CopyMemory(aFI1(0), Temp(0), BytesNeeded)
    For I = 0 To NumForms - 1
    With aFI1(I)
    ' Listenname und -größe einschließlich der Anzahl (Index).
    FormItem = PtrCtoVbString(.pName) & " - " & .Size.cx / 1000 & _
    " mm X " & .Size.cy / 1000 & " mm (" & I + 1 & ")"
    List1.AddItem FormItem
    End With
    Next I
    ClosePrinter (PrinterHandle)
    End If
    End Sub

    Private Sub UseForm(FormName As String)
    Dim RetVal As Integer

    RetVal = SelectForm(FormName, Me.hwnd)
    Select Case RetVal
    Case FORM_NOT_SELECTED ' 0
    ' Auswahl fehlgeschlagen!
    MsgBox "Formularname konnte nicht abgerufen werden", vbExclamation, _
    "Vorgang angehalten!"
    Case FORM_SELECTED ' 1
    ' Auswahl erfolgreich!
    PrintTest ' Kommentieren dieser Zeile, um Druckvorgang zu vermeiden
    Case FORM_ADDED ' 2
    ' Formular hinzugefügt und ausgewählt.
    List1.Clear ' Anzeigen des Hinzufügens im Listenfeld
    Form_Load ' durch Neuerstellen der Liste.
    End Select
    End Sub
  5. Fügen Sie im Menü Projekt ein neues Modul hinzu: Modul1.
  6. Fügen Sie den folgenden Code in Modul1 ein:
    Option Explicit

    Public Declare Function EnumForms Lib "winspool.drv" Alias "EnumFormsA" _
    (ByVal hPrinter As Long, ByVal Level As Long, ByRef pForm As Any, _
    ByVal cbBuf As Long, ByRef pcbNeeded As Long, _
    ByRef pcReturned As Long) As Long

    Public Declare Function AddForm Lib "winspool.drv" Alias "AddFormA" _
    (ByVal hPrinter As Long, ByVal Level As Long, pForm As Byte) As Long

    Public Declare Function DeleteForm Lib "winspool.drv" Alias "DeleteFormA" _
    (ByVal hPrinter As Long, ByVal pFormName As String) As Long

    Public Declare Function OpenPrinter Lib "winspool.drv" _
    Alias "OpenPrinterA" (ByVal pPrinterName As String, _
    phPrinter As Long, ByVal pDefault As Long) As Long

    Public Declare Function ClosePrinter Lib "winspool.drv" _
    (ByVal hPrinter As Long) As Long

    Public Declare Function DocumentProperties Lib "winspool.drv" _
    Alias "DocumentPropertiesA" (ByVal hwnd As Long, _
    ByVal hPrinter As Long, ByVal pDeviceName As String, _
    pDevModeOutput As Any, pDevModeInput As Any, ByVal fMode As Long) _
    As Long

    Public Declare Function ResetDC Lib "gdi32" Alias "ResetDCA" _
    (ByVal hdc As Long, lpInitData As Any) As Long

    Public Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" _
    (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

    Public Declare Function lstrcpy Lib "KERNEL32" Alias "lstrcpyA" _
    (ByVal lpString1 As String, ByRef lpString2 As Long) As Long

    ' In diesem Beispiel nicht verwendete optionale Funktionen, die jedoch nützlich sein können.
    Public Declare Function GetForm Lib "winspool.drv" Alias "GetFormA" _
    (ByVal hPrinter As Long, ByVal pFormName As String, _
    ByVal Level As Long, pForm As Byte, ByVal cbBuf As Long, _
    pcbNeeded As Long) As Long

    Public Declare Function GetForm Lib "winspool.drv" Alias "GetFormA" _
    (ByVal hPrinter As Long, ByVal pFormName As String, _
    ByVal Level As Long, pForm As Byte) As Long

    ' Konstanten für DEVMODE
    Public Const CCHFORMNAME = 32
    Public Const CCHDEVICENAME = 32
    Public Const DM_FORMNAME As Long = &H10000
    Public Const DM_ORIENTATION = &H1&

    ' Konstanten für PRINTER_DEFAULTS.DesiredAccess
    Public Const PRINTER_ACCESS_ADMINISTER = &H4
    Public Const PRINTER_ACCESS_USE = &H8
    Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
    Public Const PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED Or _
    PRINTER_ACCESS_ADMINISTER Or PRINTER_ACCESS_USE)

    ' Konstanten für Aufruf von DocumentProperties()
    Public Const DM_MODIFY = 8
    Public Const DM_IN_BUFFER = DM_MODIFY
    Public Const DM_COPY = 2
    Public Const DM_OUT_BUFFER = DM_COPY

    ' Benutzerdefinierte Konstanten für die SelectForm-Funktion in diesem Beispiel
    Public Const FORM_NOT_SELECTED = 0
    Public Const FORM_SELECTED = 1
    Public Const FORM_ADDED = 2

    Public Type RECTL
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
    End Type

    Public Type SIZEL
    cx As Long
    cy As Long
    End Type

    Public Type SECURITY_DESCRIPTOR
    Revision As Byte
    Sbz1 As Byte
    Control As Long
    Owner As Long
    Group As Long
    Sacl As Long ' ACL
    Dacl As Long ' ACL
    End Type

    ' Die beiden Definitionen für FORM_INFO_1 machen die Codierung einfacher.
    Public Type FORM_INFO_1
    Flags As Long
    pName As Long ' String
    Size As SIZEL
    ImageableArea As RECTL
    End Type

    Public Type sFORM_INFO_1
    Flags As Long
    pName As String
    Size As SIZEL
    ImageableArea As RECTL
    End Type

    Public Type DEVMODE
    dmDeviceName As String * CCHDEVICENAME
    dmSpecVersion As Integer
    dmDriverVersion As Integer
    dmSize As Integer
    dmDriverExtra As Integer
    dmFields As Long
    dmOrientation As Integer
    dmPaperSize As Integer
    dmPaperLength As Integer
    dmPaperWidth As Integer
    dmScale As Integer
    dmCopies As Integer
    dmDefaultSource As Integer
    dmPrintQuality As Integer
    dmColor As Integer
    dmDuplex As Integer
    dmYResolution As Integer
    dmTTOption As Integer
    dmCollate As Integer
    dmFormName As String * CCHFORMNAME
    dmUnusedPadding As Integer
    dmBitsPerPel As Long
    dmPelsWidth As Long
    dmPelsHeight As Long
    dmDisplayFlags As Long
    dmDisplayFrequency As Long
    End Type

    Public Type PRINTER_DEFAULTS
    pDatatype As String
    pDevMode As Long ' DEVMODE
    DesiredAccess As Long
    End Type

    Public Type PRINTER_INFO_2
    pServerName As String
    pPrinterName As String
    pShareName As String
    pPortName As String
    pDriverName As String
    pComment As String
    pLocation As String
    pDevMode As DEVMODE
    pSepFile As String
    pPrintProcessor As String
    pDatatype As String
    pParameters As String
    pSecurityDescriptor As SECURITY_DESCRIPTOR
    Attributes As Long
    Priority As Long
    DefaultPriority As Long
    StartTime As Long
    UntilTime As Long
    Status As Long
    cJobs As Long
    AveragePPM As Long
    End Type

    Public Function GetFormName(ByVal PrinterHandle As Long, _
    FormSize As SIZEL, FormName As String) As Integer
    Dim NumForms As Long, I As Long
    Dim FI1 As FORM_INFO_1
    Dim aFI1() As FORM_INFO_1 ' Arbeitsdatenfeld FI1
    Dim Temp() As Byte ' Temporäres FI1-Datenfeld
    Dim FormIndex As Integer
    Dim BytesNeeded As Long
    Dim RetVal As Long

    FormName = vbNullString
    FormIndex = 0
    ReDim aFI1(1)
    ' Erster Aufruf ruft BytesNeeded ab.
    RetVal = EnumForms(PrinterHandle, 1, aFI1(0), 0&, BytesNeeded, NumForms)
    ReDim Temp(BytesNeeded)
    ReDim aFI1(BytesNeeded / Len(FI1))
    ' Zweiter Aufruf zählt jetzt die unterstützten Formulare auf.
    RetVal = EnumForms(PrinterHandle, 1, Temp(0), BytesNeeded, BytesNeeded, _
    NumForms)
    Call CopyMemory(aFI1(0), Temp(0), BytesNeeded)
    For I = 0 To NumForms - 1
    With aFI1(I)
    If .Size.cx = FormSize.cx And .Size.cy = FormSize.cy Then
    ' Gewünschtes Formular gefunden
    FormName = PtrCtoVbString(.pName)
    FormIndex = I + 1
    Exit For
    End If
    End With
    Next I
    GetFormName = FormIndex ' Gibt Wert ungleich Null zurück, wenn Formular gefunden wird.
    End Function

    Public Function AddNewForm(PrinterHandle As Long, FormSize As SIZEL, _
    FormName As String) As String
    Dim FI1 As sFORM_INFO_1
    Dim aFI1() As Byte
    Dim RetVal As Long

    With FI1
    .Flags = 0
    .pName = FormName
    With .Size
    .cx = FormSize.cx
    .cy = FormSize.cy
    End With
    With .ImageableArea
    .Left = 0
    .Top = 0
    .Right = FI1.Size.cx
    .Bottom = FI1.Size.cy
    End With
    End With
    ReDim aFI1(Len(FI1))
    Call CopyMemory(aFI1(0), FI1, Len(FI1))
    RetVal = AddForm(PrinterHandle, 1, aFI1(0))
    If RetVal = 0 Then
    If Err.LastDllError = 5 Then
    MsgBox "Sie haben keine Berechtigungen zum Hinzufügen eines Formulars zu " & _
    Printer.DeviceName, vbExclamation, "Zugriff verweigert!"
    Else
    MsgBox "Fehler: " & Err.LastDllError, "Fehler beim Hinzufügen eines Formulars"
    End If
    AddNewForm = "Keine"
    Else
    AddNewForm = FI1.pName
    End If
    End Function

    Public Function PtrCtoVbString(ByVal Add As Long) As String
    Dim sTemp As String * 512, x As Long

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

    Public Function SelectForm(FormName As String, ByVal MyhWnd As Long) _
    As Integer
    Dim nSize As Long ' Größe von DEVMODE
    Dim pDevMode As DEVMODE
    Dim PrinterHandle As Long ' Handle an Drucker
    Dim hPrtDC As Long ' Handle an Gerätekontext für Drucker
    Dim PrinterName As String
    Dim aDevMode() As Byte ' Arbeits-DEVMODE
    Dim FormSize As SIZEL

    PrinterName = Printer.DeviceName ' Aktueller Drucker
    hPrtDC = Printer.hdc ' hDC für aktuellen Drucker
    SelectForm = FORM_NOT_SELECTED ' Festlegen als Fehler, sofern kein Zurücksetzen im Code erfolgt.

    ' Abrufen eines Handles zum Drucker.
    If OpenPrinter(PrinterName, PrinterHandle, 0&) Then
    ' Abrufen der Größe von DEVMODE.
    nSize = DocumentProperties(MyhWnd, PrinterHandle, PrinterName, 0&, _
    0&, 0&)
    ' Reservieren von Arbeitsspeicher für die aktuelle Größe des DEVMODE.
    ReDim aDevMode(1 To nSize)

    ' Ausfüllen des DEVMODE vom Drucker.
    nSize = DocumentProperties(MyhWnd, PrinterHandle, PrinterName, _
    aDevMode(1), 0&, DM_OUT_BUFFER)
    ' Kopieren des öffentlichen (vordefinierten) Teils des DEVMODE.
    Call CopyMemory(pDevMode, aDevMode(1), Len(pDevMode))

    ' Falls der Formularname "MeinBenutzerdefiniertesFormular" ist, muss sichergestelle werden, dass dieser Name existiert,
    ' bevor wir ihn verwenden. Ansonsten stammt er aus der Liste EnumForms,
    ' und eine anfängliche Prüfung ist nicht erforderlich. Beachten Sie, dass es auch möglich gewesen wäre,
    ' ein Flag zu übergeben, anstatt einen echten Namen zu prüfen.
    If FormName = "MeinBenutzerdefiniertesFormular" Then
    ' Verwenden und, falls notwendig, Hinzufügen des Formulars "MeinBenutzerdefiniertesFormular".
    ' Festlegen der gewünschten Größe des erforderlichen Formulars.
    With FormSize ' Angabe in Tausendstel Millimeter
    .cx = 214000 ' Breite
    .cy = 216000 ' Höhe
    End With
    If GetFormName(PrinterHandle, FormSize, FormName) = 0 Then
    ' Formular nicht gefunden - beide der nächsten 2 Zeilen funktionieren.
    'FormName = AddNewForm(PrinterHandle, FormSize, "MeinBenutzerdefiniertesFormular")
    AddNewForm PrinterHandle, FormSize, "MeinBenutzerdefiniertesFormular"
    If GetFormName(PrinterHandle, FormSize, FormName) = 0 Then
    ClosePrinter (PrinterHandle)
    SelectForm = FORM_NOT_SELECTED ' Auswahl fehlgeschlagen!
    Exit Function
    Else
    SelectForm = FORM_ADDED ' Formular hinzugefügt, Auswahl erfolgreich!
    End If
    End If
    End If

    ' Ändern des entsprechenden Mitglieds im DevMode.
    ' In diesem Fall sollten Sie den Formularnamen ändern.
    pDevMode.dmFormName = FormName & Chr(0) ' Muss auf NULL enden!
    ' Festlegen des Bitflags dmFields, um anzuzuzeigen, was geändert wird.
    pDevMode.dmFields = DM_FORMNAME

    ' Kopieren Sie die Änderungen zurück, und aktualisieren Sie dann DEVMODE.
    Call CopyMemory(aDevMode(1), pDevMode, Len(pDevMode))
    nSize = DocumentProperties(MyhWnd, PrinterHandle, PrinterName, _
    aDevMode(1), aDevMode(1), DM_IN_BUFFER Or DM_OUT_BUFFER)

    nSize = ResetDC(hPrtDC, aDevMode(1)) ' Zurücksetzen des DEVMODE für den DC.

    ' Schließen des Handles nach Beenden.
    ClosePrinter (PrinterHandle)
    ' Auswahl erfolgreich! Wurde das Formular jedoch hinzugefügt?
    If SelectForm <> FORM_ADDED Then SelectForm = FORM_SELECTED
    Else
    SelectForm = FORM_NOT_SELECTED ' Auswahl fehlgeschlagen!
    End If
    End Function

    Public Sub PrintTest()
    ' Ausdrucken von zwei Testseiten zur Bestätigung der Seitengröße.
    Printer.Print "Anfang Seite 1."
    Printer.NewPage
    ' Der Zeilenabstand sollte die ausgewählte Seitenhöhe widerspiegeln.
    Printer.Print "Anfang Seite 2. - Überprüfen der Seitenhöhe (Länge)."
    Printer.EndDoc
    MsgBox "Drucker überprüfen" & Printer.DeviceName, vbInformation, "Fertig!"
    End Sub
  7. Ausführen des Projekts. Das Listenfeld zeigt alle Formulare an, die vom aktuellen Drucker unterstützt werden.
  8. Klicken Sie auf Command1. Dadurch wird "MeinBenutzerdefiniertesFormular - 214 mm X 216 mm (xxx)" am Ende der Liste hinzugefügt, wobei "xxx" die dem neuen Formular zugewiesene Nummer ist.
  9. Klicken Sie auf ein Formular im Listenfeld, und klicken Sie dann auf Command2. Dadurch wird mit dem ausgewählten Formular eine Testseite an den aktuellen Drucker gedruckt.
  10. Klicken Sie das neue benutzerdefinierte Formular im Listenfeld, und klicken Sie dann auf Command3. Sie werden aufgefordert, das Löschen des Formulars zu bestätigen. Wenn Sie auf Ja klicken, wird das benutzerdefinierte Formular entfernt. Wenn Sie dies mit einem vordefinierten Formular versuchen, wird Fehler 87 ausgelöst, da nur benutzerdefinierte Formulare gelöscht werden können.

Informationsquellen

Weitere Informationen zu den in diesem Artikel verwendeten Funktionen und Typen finden Sie auf der MSDN Library-CD oder im Win32 SDK Programmer's Guide (englischsprachig).

Um weitere Informationen zu Formularen zu erhalten, klicken Sie unten auf die Artikelnummer, um den Artikel in der Microsoft Knowledge Base anzuzeigen:

157172 How to Create Custom Forms in Windows NT 4.0 and Windows 2000


Bitte beachten Sie: Bei diesem Artikel handelt es sich um eine Übersetzung aus dem Englischen. Es ist möglich, dass nachträgliche Änderungen bzw. Ergänzungen im englischen Originalartikel in dieser Übersetzung nicht berücksichtigt sind. Die in diesem Artikel enthaltenen Informationen basieren auf der/den englischsprachigen Produktversion(en). Die Richtigkeit dieser Informationen in Zusammenhang mit anderssprachigen Produktversionen wurde im Rahmen dieser Übersetzung nicht getestet. Microsoft stellt diese Informationen ohne Gewähr für Richtigkeit bzw. Funktionalität zur Verfügung und übernimmt auch keine Gewährleistung bezüglich der Vollständigkeit oder Richtigkeit der Übersetzung.
Eigenschaften

Artikelnummer: 282474 – Letzte Überarbeitung: 19.08.2003 – Revision: 1

Feedback