Selbsterstellter Panel als Bild Speichern

  • VB.NET

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Selbsterstellter Panel als Bild Speichern

    Hallo,

    Ich habe mir einen eigenen Panel erstellt, welcher eine opacity von 0.55 enthält. Auf diesem Panel kann ich auch noch per Mausklick zeichnen. Soweit funktioniert alles, nun möchte ich dieses gezeichnete als Bild abspeichern, das heißt den Panel als Bild speichern.
    Das sieht so aus:

    Quellcode

    1. Private Sub btnSpeichern_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSpeichern.Click
    2. Dim bmp As New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    3. Dim pfad As String = "***"
    4. PbZeichnen.DrawToBitmap(bmp, PbZeichnen.ClientRectangle)
    5. bmp.Save(pfad & "\" & tbBildname.Text, Drawing.Imaging.ImageFormat.Png)
    6. End Sub


    Nun bekomme ich aber nur ein weißes Bild, obwohl ich vorher dieses Panel bemalt habe.

    Der restliche Code:

    Quellcode

    1. Private Sub PbZeichnen_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PbZeichnen.MouseDown
    2. erlaubeZeichnen = True
    3. lastpoint = e.Location
    4. Points.Clear()
    5. Points.Add(e.Location)
    6. End Sub
    7. Private Sub PbZeichnen_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PbZeichnen.MouseMove
    8. Dim bitmap As Bitmap
    9. bitmap = New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    10. If erlaubeZeichnen AndAlso e.Location <> lastpoint Then
    11. Using g As Graphics = PbZeichnen.CreateGraphics 'Graphics.FromImage(bitmap)
    12. 'g.FillEllipse(New SolidBrush(Color.AliceBlue), lastpoint.X - 2 \ 2, lastpoint.Y - 2 \ 2, 2, 2)
    13. g.DrawLine(New Pen(Color.Red, 3.5), lastpoint, e.Location)
    14. lastpoint = e.Location
    15. Points.Add(e.Location)
    16. Me.DoubleBuffered = True
    17. End Using
    18. End If
    19. End Sub
    20. Private Sub PbZeichnen_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PbZeichnen.MouseUp
    21. If erlaubeZeichnen Then
    22. erlaubeZeichnen = False
    23. End If
    24. End Sub
    Du baust auf falscher Grundlage.
    Zu zeichnen ist ausschließlich im Paint-Event, und nur in das dort gegebene Graphics-Objekt. Bei den Tuts hat Freakjs was dazu gemacht.

    wenn dus zeichnen wie angegeben umgebaut hast, ists anschließend auch kein prob mehr, statt in die Graphics eines Paint-Events nun in die Graphics einer Bitmap zu zeichnen.

    ErfinderDesRades schrieb:

    Du baust auf falscher Grundlage.
    Zu zeichnen ist ausschließlich im Paint-Event, und nur in das dort gegebene Graphics-Objekt. Bei den Tuts hat Freakjs was dazu gemacht.

    wenn dus zeichnen wie angegeben umgebaut hast, ists anschließend auch kein prob mehr, statt in die Graphics eines Paint-Events nun in die Graphics einer Bitmap zu zeichnen.
    Einmal abgeändert:

    Quellcode

    1. Private Sub PbZeichnen_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PbZeichnen.Paint
    2. Dim bmp As New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    3. Me.DoubleBuffered = True
    4. With Graphics.FromImage(bmp)
    5. .DrawLine(New Pen(Color.Red, 3.5), lastpoint, Control.MousePosition)
    6. bmp.Dispose()
    7. End With
    8. End Sub


    Und nochmal abgeändert:

    Quellcode

    1. Private Sub PbZeichnen_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PbZeichnen.MouseMove
    2. Dim bmp As New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    3. If erlaubeZeichnen AndAlso e.Location <> lastpoint Then
    4. With Graphics.FromImage(bmp)
    5. lastpoint = MousePosition
    6. Points.Add(e.Location)
    7. bmp.Dispose()
    8. End With
    9. End If
    10. End Sub


    Aber es geht immer noch nicht....
    Benutze Using, um die Ressourcen der Graphics-Instanz danach freizugeben.

    dotnet-snippets.de/dns/screens…er-einer-form-SID553.aspx
    /nicht getestet

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

    Das Tutorial habe ich mir schon durchgelesen.
    Ich verstehe trotzdem nicht, wo mein Fehler ist.

    Es soll ja immer im Paint-Event gezeichnet werden das würde doch das bedeuten:

    Quellcode

    1. Private Sub PbZeichnen_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PbZeichnen.Paint
    2. Dim bmp As New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    3. 'Dim g As Graphics = e.Graphics
    4. Me.DoubleBuffered = True
    5. With Graphics.FromImage(bmp)
    6. 'e.DrawLine(New Pen(Color.Red, 3.5), lastpoint, Control.MousePosition)
    7. .DrawLine(New Pen(Color.Red, 3.5), lastpoint, Control.MousePosition)
    8. 'Invalidate()
    9. End With
    10. End Sub


    UNd dann will ich ja das beim MausMove die aktuelle Position gespeichert wird.


    Quellcode

    1. Private Sub PbZeichnen_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PbZeichnen.MouseMove
    2. ' Dim bitmap As Bitmap
    3. ' bitmap = New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    4. Dim bmp As New Bitmap(PbZeichnen.Width, PbZeichnen.Height)
    5. If erlaubeZeichnen AndAlso e.Location <> lastpoint Then
    6. lastpoint = MousePosition
    7. Points.Add(e.Location)
    8. ' Using g As Graphics = PbZeichnen.CreateGraphics
    9. ' 'g.FillEllipse(New SolidBrush(Color.AliceBlue), lastpoint.X - 2 \ 2, lastpoint.Y - 2 \ 2, 2, 2)
    10. ' g.DrawLine(New Pen(Color.Red, 3.5), lastpoint, e.Location)
    11. ' lastpoint = e.Location
    12. ' Points.Add(e.Location)
    13. ' Me.DoubleBuffered = True
    14. ' End Using
    15. End If
    16. End Sub


    Und dasselbe wenn MouseDown eintritt:

    Quellcode

    1. Private Sub PbZeichnen_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PbZeichnen.MouseDown
    2. erlaubeZeichnen = True
    3. lastpoint = e.Location
    4. Points.Clear()
    5. Points.Add(e.Location)
    6. End Sub


    Verstehe eben nicht, wo da der Fehler ist, vielleicht noch ein paar Tipps geben.


    Danke
    Du hast die 2. Bedingung übersehen:

    ErfinderDesRades schrieb:

    Zu zeichnen ist ausschließlich im Paint-Event, und nur in das dort gegebene Graphics-Objekt.
    damit ist nicht gemeint, dass du im PaintEvent dir sonstwoher ein Graphics holst, sondern nimm e.Graphics und kein anneres.

    Das mit der Bitmap kommt später.
    Deine Paint-sub ist eig Unsinn. Du holst dir das Graphics-Objekt der Picturebox (e.Graphics) und holst dir dann noch das von einer lokal erstellten Bitmap-Instanz (...FromImage). Diese Bitmap ist nur innerhalb der Sub gültig (sichtbar). Somit kanst du es auch nicht von außerhalb dieser Sub aufrufen und speichern.
    Ähnlicher Unsinn steht in deinem MouseMove-Event. Wieder eine lokale Bitmap-Instanz und zeichnen tust du auf dem Graphics-Objekt der Picturebox. Diesmal sogar mit ekliger CrateGraphics-Crap-Methode.
    Versuch das mal zu ordnen.
    Du möchtest Linien entlang der Mausbewegung zeichnen. Das entstandene Bild möchtest du als Bitmap speichern.
    Du könntest direkt auf ein global instanziertes Bild zeichnen und dieses als Image der Pictuerbox zuweisen. Dieses Bitmap bemalst du mit Using g as Graphics = Graphics.FromImage(). Nur wenn du neu beginnen möchtest, mußt du das Bitmap neu erstellen.
    Die 2. (bessere) Möglichkeit wäre, die Picturebox zu vergesen und direkt auf die Form zu zeichnen (im Form-Paint-Event mit e.Graphics). Im Mousemove speicherst du die Punkte in einer List(Of Point). Im Paint zeichnest du die Linien mit DrawLines(PouintArray) in einem Rutsch (oder schau dir Graphicspath an). Erst zum Speichern erstellst du ein Bitmap und bemalst dieses mit DrawLines(PouintArray) mittels Graphics.FromImage.

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Ich habe ja keine Picturebox sondern ein selbsterstelltes Panel, in welches ich kein Image habe.
    Deswegen kann ich dem PbZeichnen kein Bild zuweisen...

    Und ich glaube das es an dem Sub PbZeichnen_Paint liegt, weil in diesen Sub habe ich mal ein vorher funktionierenden Code eingegeben, doch dieser funktioniert nicht, ebenfalls geht er beim Debuggen gar nicht in den Sub rein...

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

    Ob Panel-Hintergrundbildle oder Picturebox-Image is eigentlich Wurscht. Obwohl, wozu gibs Pictureboxen? Ah, darstellen von Bildern. Und Panels sind Container für Steuerelemente.
    Nichtsdestotrotz kann man auf beiden malen oder wasauchimmer.
    Aber dein Vorgehen ist Crap. Lies meinen Post nochmal gaanz langsam. Du hast da nen riesen Durcheinander veranstaltet. Ich empfehle dir ein "Spielprojekt" anzulegen und das mal Schritt für Schritt durchzuspielen.

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Das ist mein aktueller Code:

    Quellcode

    1. Function PictureboxtoImage(ByVal picturebox As PictureBox)
    2. Dim pfad As String = "***"
    3. picturebox.DrawToBitmap(bmp, New System.Drawing.Rectangle(New Point(0, 0), picturebox.Size))
    4. bmp.Save(pfad & "\" & tbBildname.Text, System.Drawing.Imaging.ImageFormat.Jpeg)
    5. Return bmp
    6. End Function
    7. Private Sub btnSpeichern_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSpeichern.Click
    8. PictureboxtoImage(PictureBox1)
    9. End Sub
    10. Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    11. erlaubeZeichnen = True
    12. lastpoint = e.Location
    13. Points.Clear()
    14. Points.Add(e.Location)
    15. End Sub
    16. Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    17. If erlaubeZeichnen AndAlso e.Location <> lastpoint Then
    18. Using g = Graphics.FromImage(bmp)
    19. g.DrawLine(New Pen(DrawColour, colorWidth), lastpoint, e.Location)
    20. End Using
    21. 'Using g As Graphics = PbZeichnen.CreateGraphics
    22. ' g.DrawLine(New Pen(Color.Red, 3.5), lastpoint, Control.MousePosition)
    23. 'End Using
    24. lastpoint = e.Location
    25. Points.Add(e.Location)
    26. PictureBox1.Image = bmp
    27. End If
    28. End Sub

    Bevor jetzt gesagt wird, dass ich es im Paint-Event zeichnen soll, muss ich sagen, dass dieses Event bei mir erst gar nicht aufgerufen wird, deswegen habe ich es so gelöst und es funktioniert ja auch, bis auf die tatsache das es auf einem Tablet hinterher hängt.

    vivil schrieb:

    dass dieses Event bei mir erst gar nicht aufgerufen wird

    Wenn du mal die Doku zu diesem Event lesen tätst (MSDN), würdest du wissen, dass dieses Event gefeuert wird, wenn das entsprechende Control neu gezeichnet werden muß (Größenänderung, verschieben, usw). Wenn du das Neuzeichnen anfordern willst, mußt du dies mit Invalidate() tun.
    Du erstellst jedesmal im MouseMove ein neues Graphics-Objekt. Das ist schon mal so ne Bremse. Schmeiß das Zeichengedöns aus dem MouseMove raus. Lege dir einen globalen GraphicsPath an. Diesem kannst du Linien mit AddLine(Poin, Point) hinzufügen. Dahinter machst du PictureBox.Invalidate() um das Zeichnen auszulösen. Du kannst dabei auch ein Rectangle mitgeben, damit nicht das gesamte Bild gezeichnet wird, sondern nur der Ausschnitt(definiert durch Last- und Aktuellen Point).
    Im Picturebox-Paint tust du nur noch mit e.DrawPath(Stift, Satrtposition...) zeichnen.

    Fiel Fergnügen

    Vatter
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    Habe es jetzt geschafft, nur das Problem ist, dass ich große Lücken bekomme und es immer noch nciht schneller auf dem Tablet läuft...

    Quellcode

    1. Private Sub PictureBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseDown
    2. erlaubeZeichnen = True
    3. lastpoint = e.Location
    4. Points.Clear()
    5. Points.Add(e.Location)
    6. End Sub
    7. Private Sub PictureBox1_MouseMove(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseMove
    8. If erlaubeZeichnen Then 'AndAlso e.Location <> lastpoint Then
    9. berechnen = MousePosition - e.Location
    10. PictureBox1.Invalidate()
    11. lastpoint = e.Location
    12. 'lastpoint = MousePosition
    13. Points.Add(e.Location)
    14. 'Points.Add(MousePosition)
    15. PictureBox1.Image = bmp
    16. End If
    17. End Sub
    18. Private Sub PictureBox1_MouseUp(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles PictureBox1.MouseUp
    19. If erlaubeZeichnen Then
    20. erlaubeZeichnen = False
    21. End If
    22. End Sub
    23. Private Sub PictureBox1_Paint(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
    24. If erlaubeZeichnen Then
    25. Using g = Graphics.FromImage(bmp)
    26. g.DrawLine(New Pen(DrawColour, colorWidth), lastpoint, MousePosition - berechnen)
    27. End Using
    28. End If
    29. End Sub


    Was mache ich falsch ?!

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „vivil“ ()

    Vatter schrieb:

    Lege dir einen globalen GraphicsPath an. Diesem kannst du Linien mit AddLine(Poin, Point) hinzufügen. Dahinter machst du PictureBox.Invalidate() um das Zeichnen auszulösen. Du kannst dabei auch ein Rectangle mitgeben, damit nicht das gesamte Bild gezeichnet wird, sondern nur der Ausschnitt(definiert durch Last- und Aktuellen Point).
    Im Picturebox-Paint tust du nur noch mit e.DrawPath(Stift, Satrtposition...) zeichnen.
    :thumbsup: Seit 26.Mai 2012 Oppa! :thumbsup:
    In meinem Picturebox_Paint gibt es kein e.Drawpath..... -> Drawpath is not a member of System.Windows.Forms.PaintEventArgs.
    Wenn ich meine zuvor erstellt globale Variable benutze:

    Quellcode

    1. Private grafikPfad As GraphicsPath


    Dann kommt drawpath is not a member of System.Drawing.Drawing2D.GraphicPath...


    So und wenn ich:

    Quellcode

    1. grafikPfad.AddLine(e.Location, MousePosition - berechnen)

    mache, dann kommt der Objektverweis wurde nicht auf eine Objektinstanz festgelegt...


    Ich sehe glaube den Wald vor lauter Bäumen nicht mehr. -.-

    vivil schrieb:

    VB.NET-Quellcode

    1. Private grafikPfad As GraphicsPath
    ==>

    VB.NET-Quellcode

    1. Private grafikPfad As New GraphicsPath
    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!