In Picturebox zeichnen und dann in eine Datei speichern

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von dive26.

    In Picturebox zeichnen und dann in eine Datei speichern

    Hallo Leute,

    entschuldigt wenn ich wieder einmal eine naive "Ein- und Umsteigerfrage" habe und das ganze falsch angehe. Aber ich weis zur Zeit nicht recht weiter. Ich möchte mit der Maus auf eine Picturebox zeichnen können. Das geht soweit mit folgendem Code. Nun möchte ich den Inhalt der Picturebox in eine Datei speichern.

    Zur Info: Die Picturebox ist bereits während der Entwicklugnszeit mit einem weißen Bild (800x500 Pixel) gefüllt.

    Führe ich folgenden Code aus, dann kann ich auf der Picturebox zeichnen. Wenn ich aber die Picturebox abspeichere, dann wird nur das weiße Bild gespeichert, nicht jedoch die gezeichneten Linien (die ich aber am Bildschirm sehe).

    Wie kann ich das geladene Bilde mit den gezeichneten Linien vor dem Speichern "Zusammenführen"?

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class frm_Handschriftlich
    3. Private lastPoint As Point
    4. Private pdraw As Boolean
    5. Private cl As Color = Color.Red
    6. Private w As Integer = 4
    7. ''' <summary>
    8. ''' Speichert das Image der Picturebox in eine JPG Datei
    9. ''' </summary>
    10. ''' <param name="sender"></param>
    11. ''' <param name="e"></param>
    12. ''' <remarks></remarks>
    13. Private Sub btn_Speichern_Click(sender As Object, e As EventArgs) Handles btn_Speichern.Click
    14. Me.PictureBox1.Image.Save(Path.Combine(FlexX_Datenverzeichnis, "handschrift.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg)
    15. Me.Close()
    16. End Sub
    17. Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
    18. If e.Button = Windows.Forms.MouseButtons.Left Then
    19. pdraw = True
    20. lastPoint = e.Location
    21. End If
    22. End Sub
    23. Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    24. If pdraw AndAlso e.Location <> lastPoint Then
    25. Using g As Graphics = PictureBox1.CreateGraphics
    26. g.FillEllipse(New SolidBrush(cl), lastPoint.X - w \ 2, lastPoint.Y - w \ 2, w, w)
    27. g.DrawLine(New Pen(cl, w), lastPoint, e.Location)
    28. lastPoint = e.Location
    29. End Using
    30. End If
    31. End Sub
    32. Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
    33. pdraw = False
    34. End Sub
    35. End Class
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Danke Sonne für den Link,

    Wie bekomme ich die Funktion von "PictureBox1_MouseMove" in das Paint Event?

    Du musst Dir die praktische Anwendung so vorstellen:

    Das Fenster mit der "Zeichenfläche" (Picturebox) wird geöffnet. Der User kann nun mit der Maus oder mit dem Finger am Touchscreen etwas auf diese "Zeichenfläche" kritzeln und das ganze dann mit "Absenden" als Datei speichern.

    LG Roland
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    Wozu brauchst du unbedingt eine PictureBox? Du kannst ein Panel draufmachen und im MausMove-Event Me.Invalidate aufrufen, damit wird die ganze Form neu gezeichnet (und somit Paint-Event aufgerufen). Dieser Methode kannst du auch Koordinaten eines Rechtecks (also des Panels dann) übergeben, falls auf deiner Form sich weitere Elemente befindet, die nicht neu gezeichnet werden sollen.
    Super, vielen Dank LaMiy!!!!

    Mit Deinem Tipp und mit der Verwendung eines Initialbildes im Format jpg (statt gif oder bmp) funktioniert das nun einwandfrei und so wie von mir erwartet. Danke, Danke, Danke!! :thumbsup:

    VB.NET-Quellcode

    1. Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    2. If pdraw AndAlso e.Location <> lastPoint Then
    3. 'Using g As Graphics = PictureBox1.CreateGraphics
    4. Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
    5. g.FillEllipse(New SolidBrush(cl), lastPoint.X - w \ 2, lastPoint.Y - w \ 2, w, w)
    6. g.DrawLine(New Pen(cl, w), lastPoint, e.Location)
    7. lastPoint = e.Location
    8. End Using
    9. PictureBox1.Refresh()
    10. End If
    11. End Sub
    Bilder
    • 13052014173459.jpg

      128,35 kB, 800×600, 218 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    @sonne75 Versteh' ich nicht so ganz. Er möchte ja auf das Bild zeichnen. Da muss ich ja nicht die Form neuzeichnen wenn sich das Bild im Panel (oder einem anderen Container) befindet.
    Aber ich glaube ich weiß worauf du hinaus willst.

    Btw. Das Form-Paint-Event wird nicht aufgerufen, sondern ausgelöst. Lediglich die Behandlermethode wird aufgerufen.
    (Sorry wegen der Klugscheißerei, aber so wie ich dein Auftreten kenne nimmst du es mir nicht übel und freust dich über das neue Wissen :D
    (leider konnte ich kein typ. DataSet mit reinbringen :P ))

    dive26 schrieb:

    Zusammenführen
    Probier mal dies, eine separate Bitmap, Code kann noch optimiert werden:

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Private lastPoint As Point
    4. Private pdraw As Boolean
    5. Private cl As Color = Color.Red
    6. Private w As Integer = 4
    7. Private FlexX_Datenverzeichnis As String = "c:\temp\"
    8. Private bmp As Bitmap = New Bitmap(500, 500)
    9. ''' <summary>
    10. ''' Speichert das Image der Picturebox in eine JPG Datei
    11. ''' </summary>
    12. ''' <param name="sender"></param>
    13. ''' <param name="e"></param>
    14. ''' <remarks></remarks>
    15. Private Sub btn_Speichern_Click(sender As Object, e As EventArgs) Handles Button1.Click
    16. Me.bmp.Save(Path.Combine(FlexX_Datenverzeichnis, "handschrift.jpg"), System.Drawing.Imaging.ImageFormat.Jpeg)
    17. Me.Close()
    18. End Sub
    19. Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
    20. If e.Button = Windows.Forms.MouseButtons.Left Then
    21. pdraw = True
    22. lastPoint = e.Location
    23. End If
    24. End Sub
    25. Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    26. If pdraw AndAlso e.Location <> lastPoint Then
    27. Using g As Graphics = Graphics.FromImage(bmp) 'PictureBox1.CreateGraphics
    28. g.FillEllipse(New SolidBrush(cl), lastPoint.X - w \ 2, lastPoint.Y - w \ 2, w, w)
    29. g.DrawLine(New Pen(cl, w), lastPoint, e.Location)
    30. lastPoint = e.Location
    31. End Using
    32. End If
    33. PictureBox1.Image = bmp
    34. End Sub
    35. Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
    36. pdraw = False
    37. End Sub
    38. Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    39. Me.PictureBox1.Image = New Bitmap(500, 500)
    40. End Sub
    41. End Class
    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!

    LaMiy schrieb:

    leider konnte ich kein typ. DataSet mit reinbringen

    Ich bin mit @ErfinderDesRades weder verwandt noch verschwägert :P

    LaMiy schrieb:

    Er möchte ja auf das Bild zeichnen


    Muss aber nicht, das war meine Aussage. Er kann auch direkt auf Form zeichnen (so habe ich es zumindest in diversen Threads aufgeschnappt, dass es die bevorzugte Art und Weise ist). Und dafür muss dann halt Me.Invalidate aufgerufen werden, dafür kann man den Bereich einschränken.

    Und natürlich nehme ich es nicht übel, bin selbst häufig genug eine Korinthenkackerin :P
    Danke Euch allen,

    dass ich nicht zwingend auf eine Picturebox zeichnen muss, sondern auch auf eine Form oder ein Panel kann, dass habe ich verstanden. Danke für den Hinweis.

    @Rod
    Ich muss keine anderen Bitmaps zur Laufzeit laden. In der Entwicklungszeit wird einfach ein weißes JPG-Bild (weißer Hintergrund) aus den Ressourcen eingebunden und das reicht vollkommen für meinen Einsatzzweck.

    Gespeichert wird das Bild dann natürlich auch unter einem anderen Dateinamen- und Pfad. Der Fixpfad ist nur zu Testzwecken drin.

    Und entschuldigt, dass ich kein Dataset verwendet habe :D
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Ich muss keine anderen Bitmaps zur Laufzeit laden
    Ich auch nicht, ich brauch nicht mal eine leere Datei. :D
    Das, was Du im Designer gemacht hast, hab ich im Code gemacht und ist somit für alle hier sofort ersichtlich. Dir nun auch?
    Meine Bitmap muss nur noch "geweißt" 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!
    Versteh ich schon, Rod.

    Aber ich müsste bei Deiner Variante bei der Installation noch eine Datei irgendwo mit hin kopieren, wo die Gefahr besteht, dass diese vom User irgendwann einmal gelöscht wird und dann nicht mehr für diese Zwecke vorhanden ist. Daher befindet die sich in den Ressourcen.
    Natürlich lade ich das Bild im onLoad Ereignis der Form nochmals rein, da ja bei jedem Aufruf eine weiße Zeichenfläche vorhanden sein soll:

    VB.NET-Quellcode

    1. PictureBox1.Image = My.Resources.weiss800x5001


    Das oben gepostete war ja nur für meine Frage bezüglich des Zeichnens und Speicherns.
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    dive26 schrieb:

    Aber ich müsste bei Deiner Variante bei der Installation noch eine Datei irgendwo mit hin kopieren, wo die Gefahr besteht, dass diese vom User irgendwann einmal gelöscht wird


    Eben nicht. ;)

    Das von Rod ist die konsequente Umsetzung seines oft postulierten Paradigmas Daten und UI zu trennen. Du hälst deine Daten (das Bild) in der UI vor - nämlich in der PictureBox. Der korrekte Ansatz wäre, das Bild im Speicher zu "zeichnen" und die PictureBox (oder die Form oder das Panel oder...) nur zu dessen Anzeige zu verwenden.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.

    sonne75 schrieb:

    Vielleicht die?
    Glaub nicht.

    dive26 schrieb:

    bei der Installation
    Meine Bitmap wird während der Laufzeit generiert, ohne Datei.
    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!
    Hier zur Aufklärung der vollständige Sourcecode und als Anhang das Ergebnis als Bonausdruck. Dieser Programmteil ist fertig und funktioniert auch soweit einwandfrei. Ich könnte das Image auche während der Laufzeit erzeugen, müsste es dann aber noch weiß einfärben. Der Vorteil einer externen Grafik ist, dass ich (falls notwendig) auch Wasserzeichen oder andere Vorgaben in diese Ressoursendatei aufnehmen könnte. Aber passt so, ich habe jetzt den Beitrag von Rod nochmals durchgelesen und gesehen was er meinte. Danke nochmals.

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class frm_Handschriftlich
    3. Private lastPoint As Point
    4. Private pdraw As Boolean
    5. Private cl As Color = Color.Black
    6. Private w As Integer = 4
    7. ''' <summary>
    8. ''' Speichert das Image der Picturebox in eine JPG Datei mit dem Namen die dieser Programmfunktion über die
    9. ''' Variable "HandschriftlichBildName" übergeben wurde
    10. ''' </summary>
    11. ''' <param name="sender"></param>
    12. ''' <param name="e"></param>
    13. ''' <remarks></remarks>
    14. Private Sub btn_Speichern_Click(sender As Object, e As EventArgs) Handles btn_Speichern.Click
    15. Me.PictureBox1.Image.Save(Path.Combine(FlexX_Datenverzeichnis, "temp", HandschriftlichBildName + ".jpg"), System.Drawing.Imaging.ImageFormat.Jpeg)
    16. Me.Close()
    17. End Sub
    18. ''' <summary>
    19. ''' Abbrechen wird gedrückt. Die globale Variable "HandschriftlichBildName" wird geleert und
    20. ''' übergibt somit der aufrufenden Form die Info dass abgebrochen wurde
    21. ''' </summary>
    22. ''' <param name="sender"></param>
    23. ''' <param name="e"></param>
    24. ''' <remarks></remarks>
    25. Private Sub btn_abbrechen_Click(sender As Object, e As EventArgs) Handles btn_abbrechen.Click
    26. HandschriftlichBildName = ""
    27. Me.Close()
    28. End Sub
    29. Private Sub PictureBox1_MouseDown(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseDown
    30. If e.Button = Windows.Forms.MouseButtons.Left Then
    31. pdraw = True
    32. lastPoint = e.Location
    33. End If
    34. End Sub
    35. Private Sub PictureBox1_MouseMove(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseMove
    36. If pdraw AndAlso e.Location <> lastPoint Then
    37. Using g As Graphics = Graphics.FromImage(PictureBox1.Image)
    38. g.FillEllipse(New SolidBrush(cl), lastPoint.X - w \ 2, lastPoint.Y - w \ 2, w, w)
    39. g.DrawLine(New Pen(cl, w), lastPoint, e.Location)
    40. lastPoint = e.Location
    41. End Using
    42. PictureBox1.Refresh()
    43. End If
    44. End Sub
    45. Private Sub PictureBox1_MouseUp(sender As Object, e As MouseEventArgs) Handles PictureBox1.MouseUp
    46. pdraw = False
    47. End Sub
    48. Private Sub frm_Handschriftlich_Load(sender As Object, e As EventArgs) Handles Me.Load
    49. lbl_Artikel.Text = "Handschriftliche Information zu " + vbCrLf + Artikelliste(VariablerPreisArtikelIndex).Artikelbezeichnung + "(" + HandschriftlichBildName + ")"
    50. PictureBox1.Image = My.Resources.weiss800x5001
    51. End Sub
    52. End Class

    Bilder
    • beleg.jpg

      155,98 kB, 414×725, 193 mal angesehen
    • Handschriftlich.jpg

      88,39 kB, 786×586, 160 mal angesehen
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dive26“ ()