Drucken via PrintDocument

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Drucken via PrintDocument

    Hallo!

    Ich habe eine Form, in der über mehrere Steuerelemente ein Rezept steht.

    Das erste ist eine TextBox in der der Titel des Rezepts steht.
    Das zweite Steuerelement ist eine PictureBox in der ein Bild vom Rezept ist.
    Das dritte Steuerlement ist eine TextBox, in der eine Beschreibung des Rezepts steht.
    Danach folgt eine ListView in der die Zutaten aufgelistet sind.
    Darunter sind zur Laufzeit erstellte TextBoxen, eine für jeden Arbeitsschritt.
    Zum schluß folgen NumericUpDows, mit Nährstoffwerten.

    Wenn ich das Rezept nun wie folgt drucke:

    VB.NET-Quellcode

    1. Dim Antwort As Integer
    2. Antwort = PrintDialog1.ShowDialog()
    3. If Antwort = DialogResult.OK Then
    4. Select Case FensterArt
    5. Case 1
    6. DruckBlock = 0
    7. LetztSchritt = 1
    8. LetztZeile = ""
    9. Dim frm As Rezept = Me.ActiveMdiChild
    10. Me.PrintDocument1.DefaultPageSettings.Landscape = False
    11. Me.PrintDocument1.DocumentName = frm.Text
    12. Me.PrintDocument1.Print()
    13. End Select
    14. End If


    wird nur der Titel, das Bild und die Beschreibung gedruckt.

    Wenn ich wie folgt die Druckvorschau öffne:

    VB.NET-Quellcode

    1. Using dlg As New PrintPreviewDialog
    2. Select Case FensterArt
    3. Case 0
    4. Exit Sub
    5. Case 1
    6. DruckBlock = 0
    7. Drucken = True
    8. Dim frm As Rezept = Me.ActiveMdiChild
    9. Me.PrintDocument1.DefaultPageSettings.Landscape = False
    10. Me.PrintDocument1.DocumentName = frm.Text
    11. End Select
    12. dlg.Document = Me.PrintDocument1
    13. dlg.ShowDialog()
    14. End Using


    wird jedoch das komplette Rezept angezeigt

    Wenn ich das Rezept aus der Druckvorschau heraus drucke, wird nur die letzte Seite gedruckt.

    Wo liegt hier der Fehler?
    RfG wird sicherlich gleich seine Threads posten, aber wenn Du PrintDocument.Print aufrufst, musst Du im PrintDocument_Print-EventHandler auch mittels e.Graphics alles reinzeichnen, was Du wo haben willst.
    Drucken mehrseitiger Dokumente :D
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Selter98 schrieb:

    Wo liegt hier der Fehler?
    Deine PrintPage-Routine ist falsch.
    Der Link steht bei @VaporiZed ;) , poste mal Deinen Code.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die gesamte Routine ist 421 Zeilen lang. Daher poste ich erstmal den Anfang der Sub und den Druck-Block mit der Zutaten-Liste.

    Der Anfang der Routine:

    VB.NET-Quellcode

    1. g.PageUnit = GraphicsUnit.Millimeter
    2. Select Case FensterArt
    3. Case 0
    4. Exit Sub
    5. Case 1
    6. Me.PrintDocument1.DefaultPageSettings.Landscape = False
    7. End Select
    8. Dim rc = g.VisibleClipBounds
    9. Dim margin = Me.PrintDocument1.DefaultPageSettings.Margins
    10. margin.Left = 4
    11. margin.Top = 4
    12. margin.Right = 4
    13. margin.Bottom = 4
    14. rc.Offset(margin.Left, margin.Top) ' obere linke Ecke
    15. rc.Width -= (margin.Left + margin.Right) ' neue Breite
    16. rc.Height -= (margin.Top + margin.Bottom) ' neue Höhe
    17. Druckx = 10
    18. Drucky = 10

    Als erstes wird das Papierformat nach der Fensterart eingestellt. Da ich erstmal nur Rezept-Fenster deklariert habe, wird im Hoch-Format gedruckt. Später gibt es noch weitere Fensterarten, bei denen eigine im Querformat gedruckt werden. Der Rest sind Positionsangaben.

    VB.NET-Quellcode

    1. If DruckBlock <= 1 Then

    Die weitere Routine habe ich in meheren Druck-Blöcken eingeteilt, damit sich das Programm daran erinnert, wo es gerade war, wenn eine Seite Voll ist.

    VB.NET-Quellcode

    1. frm.Label8.Text = "Zutaten für " & frm.NumericUpDown2.Value & " Portionen:"
    2. SchriftHöhe = frm.Label8.Height
    3. Kette = frm.Label8.Font.ToString
    4. p1 = InStr(Kette, "Name")
    5. p2 = InStr(Kette, "Size")
    6. p3 = InStr(Kette, "Units")
    7. p4 = InStr(Kette, "GdiCharSet")
    8. p5 = InStr(Kette, "GdiVerticalFont")
    9. p7 = InStr(Kette, "]")
    10. Schrift = Mid(Kette, p1 + 5, p2 - p1 - 7)
    11. Kette2 = Mid(Kette, p2 + 5, p3 - p2 - 7)
    12. p6 = InStr(Kette2, ",")
    13. If p6 <> 0 Then Mid(Kette2, p6, 1) = "."
    14. Größe = SchriftHöhe '/ (1 / 72) / 2.54
    15. Einheit = Val(Mid(Kette, p3 + 6, p4 - p3 - 8))
    16. Satz = Val(Mid(Kette, p4 + 11, p5 - p4 - 13))
    17. Kette2 = Mid(Kette, p5 + 16, p7 - p6 - 16)
    18. If Kette2 = "False" Then Vertikal = False Else Vertikal = True
    19. br = New SolidBrush(Color.FromArgb(255, 0, 0, 0))

    Einem unsichtbarem Label wird ein Text zu gewiesen, der gedruckt werden soll. Diese Zeile ist im Rezept-Fenster nicht zu sehen, soll aber so gedruckt werden. Anhand des Textes wird die Schriftgröße, usw. ermittelt.

    VB.NET-Quellcode

    1. ​If Drucken Then g.DrawString(frm.Label8.Text, New Font(Schrift, Größe, 0, Einheit, Satz, Vertikal), br, New Point(Druckx, Drucky))

    Der Text wird dann gedruckt, wenn diese Zeile noch nicht gedruckt wurde.

    VB.NET-Quellcode

    1. ​Drucky = Drucky + 7

    Die nächste Zeile wird 7 mm tiefer gedruckt.

    VB.NET-Quellcode

    1. ​For i = 1 To frm.ListView1.Items.Count

    Es werden alle Zutaten aus der ListView ausgelesen.

    VB.NET-Quellcode

    1. ​ frm.Label7.Text = ""
    2. If frm.ListView1.Items(i - 1).Text <> "" Then
    3. frm.Label7.Text = frm.ListView1.Items(i - 1).Text & " "
    4. End If
    5. If frm.ListView1.Items(i - 1).SubItems(1).Text <> "" Then
    6. frm.Label7.Text = frm.Label7.Text & frm.ListView1.Items(i - 1).SubItems(1).Text & " "
    7. End If
    8. If frm.ListView1.Items(i - 1).SubItems(2).Text <> "" Then
    9. frm.Label7.Text = frm.Label7.Text & frm.ListView1.Items(i - 1).SubItems(2).Text & " "
    10. End If
    11. If frm.ListView1.Items(i - 1).SubItems(3).Text <> "" Then
    12. frm.Label7.Text = frm.Label7.Text & frm.ListView1.Items(i - 1).SubItems(3).Text & " "
    13. End If
    14. If frm.ListView1.Items(i - 1).SubItems(4).Text <> "" Then
    15. frm.Label7.Text = frm.Label7.Text & frm.ListView1.Items(i - 1).SubItems(4).Text & " "
    16. End If

    Das unsichtbare Label im Rezeptfenster ist zunächst leer. Dann werden nach und die Einzelheiten aus der Zutatenliste hinzugefügt, um zusätzliche Leerzeichen zu verhindern, falls eine Zutatenangabe leer ist.

    VB.NET-Quellcode

    1. ​ SchriftHöhe = frm.Label7.Height
    2. Kette = frm.Label7.Font.ToString
    3. p1 = InStr(Kette, "Name")
    4. p2 = InStr(Kette, "Size")
    5. p3 = InStr(Kette, "Units")
    6. p4 = InStr(Kette, "GdiCharSet")
    7. p5 = InStr(Kette, "GdiVerticalFont")
    8. p7 = InStr(Kette, "]")
    9. Schrift = Mid(Kette, p1 + 5, p2 - p1 - 7)
    10. Kette2 = Mid(Kette, p2 + 5, p3 - p2 - 7)
    11. p6 = InStr(Kette2, ",")
    12. If p6 <> 0 Then Mid(Kette2, p6, 1) = "."
    13. Größe = SchriftHöhe '/ (1 / 72) / 2.54
    14. Einheit = Val(Mid(Kette, p3 + 6, p4 - p3 - 8))
    15. Satz = Val(Mid(Kette, p4 + 11, p5 - p4 - 13))
    16. Kette2 = Mid(Kette, p5 + 16, p7 - p6 - 16)
    17. If Kette2 = "False" Then Vertikal = False Else Vertikal = True
    18. br = New SolidBrush(Color.FromArgb(255, 0, 0, 0))

    Auch hier werden Schriftgröße usw. ausgelesen,

    VB.NET-Quellcode

    1. ​Drucky = Drucky + 5

    Die nächste Zeile wird 5 mm tiefer gedruckt.

    VB.NET-Quellcode

    1. If Not Drucken Then
    2. If frm.Label7.Text = LetztZeile Then
    3. Drucken = True
    4. Drucky = 10
    5. Absatz = 10
    6. End If
    7. Else
    8. LetztZeile = frm.Label7.Text
    9. End If

    Wenn noch nicht gedruckt werden soll, wird gewartet, bis die letzte Zeile erreicht wurde, die auf der vorherigen Seite gedruckt wurde wurde. Dann werden die Druckpositionen auf Anfangsposition gebracht. Wenn bereits gedruckt wird, soll sich das Programm die aktuelle Zeile merken.

    VB.NET-Quellcode

    1. If Drucky > 290 Then
    2. Drucky = 10
    3. DruckBlock = 1
    4. Drucken = False
    5. DruckSeite = DruckSeite + 1 ' nächste Seite
    6. e.HasMorePages = DruckSeite ' True bei index >= 2
    7. Exit Sub
    8. End If

    Sobald die aktuelle Druckzeile tiefer als 290 mm liegt, soll die nächste Zeile gedruckt werden. Dazu wird die Druckposition auf die erste Zeile gebracht, den aktuellen Druck-Block gemerkt und Drucken auf False gesetzt, damit die bisher gedruckten Zeile nicht wiederholt gedruckt werden. Die Druckseite wird um 1 erhöht. Danach wird die Sub beendet, da es sonst zu einer Endlos-Schleife kommt.

    Auf diese Art und Weise habe ich auch die anderen Druck-Blöcke geschrieben.
    Argh, meine Augen bluten! Option Strict Off, Default-named CEs, ListView, VB6-Namespace! <X Aber mit frm.Label7.Text besteht die Hoffnung, dass zumindest Form-Instanziierung verwendet wird. Oder wie genau ist frm definiert?

    VB.NET-Quellcode

    1. DruckSeite = DruckSeite + 1
    2. e.HasMorePages = DruckSeite

    Sicher, dass das gut geht? e.HasMorePages wird immer True sein, da nur die Null zu einem False uminterpretiert (Stichwort Option Strict) wird.

    btw: DruckSeite = DruckSeite + 1 -> DruckSeite += 1
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    frm wird noch vor dem ersten Druckblock definiert, nach dem die FensterArt selectiert wurde:

    VB.NET-Quellcode

    1. ​Select Case FensterArt
    2. Case 0
    3. Exit Sub
    4. Case 1
    5. Dim frm As Rezept = Me.ActiveMdiChild
    6. If DruckBlock <= 0 Then


    Im ersten Druckblock werden Titel, Bild und Beschreibung gedruckt.
    @Selter98 Du hast ein Problem, Du suchst Hilfe.
    Wir wollen helfen, müssen aber nicht.
    Also:
    Fang an und schmeiß den VB6-Ranz raus, indem Du den VisualBasic-Namespace eliminierst: Visual Studio - Empfohlene Einstellungen
    Dann sprechen wir die selbe Sprache: VB.NET.
    Poste danach Dein bereinigtes Projekt (ohne bin- und obj-Verzeichnis) als ZIP im Anhang: Erweiterte Antwort -> Dateianhänge -> Hochladen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Der ganze Post#4 ist m.E. voll mit vielen für uns irrelevanten Informationen. Ok, RfG hat die Print-Routine erfragt. Wenn wir jetzt aber nur Stückchen erhalten + Erklärungen, was der Code macht (vielen Dank dafür, aber ich glaube, wir kommen selbst dahinter), dann kommen wir hier nicht weiter. Die eigentlich relevanten "Druck"befehle sind hier nur in 2 Zeilen: eine bedingte g.DrawString-Zeile und e.HasMorePages. Und die sind m.E. aus dem Zusammenhang gerissen. So ist Hilfe nicht möglich.
    Für lange Codepassagen gibt es den Spoiler.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Einen Fehler habe ich schon gefunden:

    In der 1. Routine habe ich vergessen Drucken auf True zu setzen. Damit werden jetzt alle Seiten gedruckt.

    Jedoch wird aus der Seitenansicht heraus immer noch nur die letzte Seite gedruckt.

    Edit:
    Gelöst:
    Jetzt wird alles gedruckt, nachdem ich diese Parameter am Ende der PrintPage-Routine zurückgesetzt habe:

    VB.NET-Quellcode

    1. DruckBlock = 0
    2. LetztSchritt = 1
    3. LetztZeile = ""
    4. DruckSeite = 0
    5. Drucken = True

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Selter98“ ()

    @Selter98 Wenn Du nicht willst, dass Dir hier geholfen wird
    oder
    wenn Du Deinen ober streng geheimen Code nicht offenbaren willst,
    kann Dir hier auch nicht geholfen werden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!