GDI+ Zeichenaktionen verschiedener Buttons unlöschbar direkt auf einer Form wiedergeben

  • VB.NET

Es gibt 22 Antworten in diesem Thema. Der letzte Beitrag () ist von Duster.

    GDI+ Zeichenaktionen verschiedener Buttons unlöschbar direkt auf einer Form wiedergeben

    Hallo Leute,

    Ich habe in der letzten Zeit das Lehrbuch von Doberenz, Gewinnus amazon.de/Visual-Basic-2015-Gr…gen&qid=1575837733&sr=8-4
    durchgearbeitet. Ich kann das Buch jedem Einsteiger nur wärmstens empfehlen ;) . Ich kam mit dem Material, dem Schreibstiel und dem Aufbau dieses Buches sehr gut zurecht und habe sehr viel daraus gelernt. Am Ende jeden Kapitels habe ich immer ein kleines eigenes kleines Lernprojekt geschrieben das das Gelernte widergespiegelt und vertieft hat. Das lie immer reibungslos!!!!

    Nun bin ich bei einem der Bonuskapitel (GDI+). Auch hier lief alles sehr gut.
    Bei meinem Lernprojekt gibt es jetzt aber eine kleine Ungereimtheit. Ich möchte die verschiedenen Zeichenoperationen (Pens, Brushes, Regions, Bitmaps etc.) mit Hilfe verschiedener Controls (Buttons, ListBoxen, Sliders etc.) darstellen. Ich möchte direkt auf die Form zeichnen also keine PictureBox verwenden und die Zeichnungen sollen bei Größenänderungen oder Überlappungen mit anderen Fenstern nicht gelöscht werden.

    Im Buch wird beim Zeichnen mit CreateGraphics() gearbeitet. Nach einigen Recherchen mit Dr.Google und vor allem hier im Forum habe entdeckt wie und warum CreateGraphics() böse ist und dass nur im PaintEvent des betreffenden Controls in meinem Falle der Form gezeichnet werden sollte. Das habe ich natürlich befolgt. ;)

    Die Sache sieht jetzt so aus: Ich habe in meinem BeispielProjekt 2 Buttons. Wird auf einen der beiden geklickt wird dessen Nummer in einer privaten Integer-Variablen gespeichert und es wird an Invalidate(rect) eine Rectanglestruktur übergeben die die Form zwingt diesen Bereich neu zu zeichen.
    Es werden beide Zeichnungen parallel auf der Form dargestellt aber nur die die zuletzt gezeichnet wurde wird bei einer Größenänderung der Form nicht gelöscht, die andere schon :( .

    Das ist eigentlich klar denn das Invalidate(rect) erzwingt ja nur das Neuzeichnen eben dieses in der Rectanglestruktur angegebenen Bereiches und nicht beider Bereiche.

    Aber wie kann ich es anstellen dass alle durch Buttons, Sliders etc. ausgeführten Zeichnungen nicht gelöscht werden ?( .

    Ich suche und probiere schon seit einigen Tagen aber zu diesem Problem finde ich einfach keine Lösung.
    Das Beispielprojekt habe ich zur besseren Veranschaulichung auch angehängt!

    Könnt Ihr mir da weiterhelfen?

    Hier der Source:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private ButtonNumber As Integer = 0
    4. Private Sub CmdTranslateT_Click(sender As Object, e As EventArgs) Handles CmdTranslateTransform.Click
    5. Dim rect As New Rectangle(0, 0, 102, 102)
    6. ButtonNumber = 1
    7. Me.Invalidate(rect)
    8. End Sub
    9. Private Sub CmdScaleT_Click(sender As Object, e As EventArgs) Handles CmdScaleT.Click
    10. Dim rect As New Rectangle(250, 50, 102, 102)
    11. ButtonNumber = 2
    12. Me.Invalidate(rect)
    13. End Sub
    14. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    15. Select Case ButtonNumber
    16. Case 1
    17. e.Graphics .DrawRectangle(New Pen(Color.Red),0, 0, 101, 101)
    18. e.Graphics.DrawEllipse(New Pen(Color.Black), 0, 0, 100, 100)
    19. Case 2
    20. e.Graphics .DrawRectangle(New Pen(Color.Red),250, 50, 101, 101)
    21. e.Graphics.DrawEllipse(New Pen(Color.Black), 250, 50, 100, 100)
    22. End Select
    23. End Sub
    24. End Class


    Vielen Dank für Eure Mühe und Hilfe vorab,
    Duster
    Dateien
    • GDI_Plus_01.1.7z

      (27,08 kB, 13 mal heruntergeladen, zuletzt: )
    So:

    VB.NET-Quellcode

    1. private _PenRed as New Pen(Color.Red)
    2. private _PenBlack as New Pen(Color.Black)
    3. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    4. e.Graphics .DrawRectangle(_PenRed,0, 0, 101, 101)
    5. e.Graphics.DrawEllipse(_PenBlack, 0, 0, 100, 100)
    6. e.Graphics .DrawRectangle(_PenRed,250, 50, 101, 101)
    7. e.Graphics.DrawEllipse(_PenBlack, 250, 50, 100, 100)
    8. End Sub

    Ggf. gleich Pens.Black und Pens.Red verwenden, da man sonst die beiden Objekte disposen müsste?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Häufig von mir verwendete Abkürzungen: CEs = control elements (Labels, Buttons, DGVs, ...) und tDS (typisiertes DataSet)
    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht in den Spekulatiusmodus gehen.
    @Erfinder des Rades, VaporiZed

    danke für Eure schnellen Antworten.
    Wenn ich den Code in das Paint-Ereignis setze wird doch alles gleich beim Amzeigen der Form gezeichnet. Gelöscht werden kann dann keine der beiden Zeichnungen.

    Es geht mir doch aber danum daß ich Button1 klicke und die erste Zeichnung wird auf die Form geblittet, dann klicke ich auf Button2 und die 2. Zeichnung wird zu der ersten auf die Form gemalt, beide sollen nicht durch Größenänderungen oder Überlappungen der Form gelöscht werden können?!


    Vielen Dank für Eure Hilfe,
    Duster
    @Duster Dann mach Dir kommunizierende Flags (Boolea Variable), die bei Button_Click gesetzt werden. Im Paint-Event wird dann nur bei gesetztem Flag die jeweilige Figur gezeichnet.
    Feddich.
    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!
    @RodFromGermany
    Danke für Deine schnelle Hilfe.
    Das habe ich auch schon ausprobiert.
    Ist das nicht genau das gleiche wie die Buttonnumber Variable im gegenwärtigen Code.
    Ich muss doch prüfen welchen Button geklickt wurde und welche Zeichenfunktionen von diesem Button angekickt werden.
    Im Paint-Event wird dies geprüft und der betreffende Code des jeweiligen Buttons ausgeführt.
    Beide Bulder werden auch gemalt aber nur die letzte Zeichnung die ausgeführt wird kann nicht gelöscht werden, die vorherige wird bei Größenänderungen gelöscht.
    Mache ich da was mit invalidate() falsch?

    @VaporiZed
    Stimmt, habs umgestellt/ berichtigt

    Ich hab im Forum einige Beispiele mit FromBitmap() gefunden die ich noch genauer durchlesen muss aber das hat doch mit meinem Problem nichts zu tun?!

    Vielen Dank für Eure Mühe und Hilfe,
    Duster

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

    @RodFromGermany
    Tut mir leid aber ich bin mir nicht sicher ob ich Dich richtig verstanden habe.
    Könntest Du ein bisschen genauer werden?

    Ist die Frage so dämlich oder habt Ihr sie schon beantwortet und ich habs nicht gemerkt?

    Vielen Dank für Deine Mühe und Hilfe,
    Duster

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

    Zeichnungen müssen, solange sie sichtbar sein sollen, im Paint Event gezeichnet werden. Mach dir zwei Flags die für deine zwei Zeichenbereiche stehen, setze die im Click Handler des jeweiligen Button auf True und lasse anschließend it Invalidate() den Bereich neu zeichnen. Im Paint Event zeichnest du den jeweiligen Bereich nur, wenn sein Flag true ist.
    @Duster So was (Pseudocode):

    VB.NET-Quellcode

    1. Flag1 = False
    2. Sub () Handles Button1.Click
    3. Flag1 = True
    4. Invalidate()
    5. End Sub
    6. Sub Paint()
    7. If Flag1 Then
    8. MALE_DAS_WAS_BEI_BUTTON_1_ZU_MALEN_IST
    9. End If
    10. End Sub
    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!

    ErfinderDesRades schrieb:

    oder habich was übersehen?
    Haste nich.
    Im Titel steht gaaaaaanz groß

    Duster schrieb:

    unlöschbar
    @Duster Wenn Du die wieder löschen willst, nusst Du einfach das Flag zurücksetzen und die Form invalidaten. ;)
    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!

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

    @RodFromGermany, ErfinderDesRades
    Vielen Dank für Eure Hilfe!
    Hier nochmal der aktualisierte Source-Code:

    Source-Code:

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private FlagCmdTransT As Boolean = False
    4. Private FlagCmdScaleT As Boolean = False
    5. Private rect1 As New Rectangle(0, 0, 101, 101)
    6. Private rect2 As New Rectangle(250, 50, 101, 101)
    7. Private Sub CmdTranslateT_Click(sender As Object, e As EventArgs) Handles CmdTranslateTransform.Click
    8. FlagCmdTransT = True
    9. Me.Invalidate(rect1)
    10. End Sub
    11. Private Sub CmdScaleT_Click(sender As Object, e As EventArgs) Handles CmdScaleT.Click
    12. FlagCmdScaleT = True
    13. Me.Invalidate(rect2)
    14. End Sub
    15. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    16. If FlagCmdTransT = True Then
    17. e.Graphics.DrawRectangle(Pens.Red, 0, 0, 100, 100)
    18. e.Graphics.DrawEllipse(Pens.Black, 0, 0, 100, 100)
    19. End iF
    20. If FlagCmdScaleT = True
    21. e.Graphics .DrawRectangle(Pens.Red,250, 50, 100, 100)
    22. e.Graphics.DrawEllipse(Pens.Black, 250, 50, 100, 100)
    23. End If
    24. End Sub
    25. Private Sub CmdClearObjOne_Click(sender As Object, e As EventArgs) Handles CmdClearObOne.Click
    26. Me.Invalidate(rect1)
    27. FlagCmdTransT = False
    28. End Sub
    29. Private Sub CmdClearObjTwo_Click(sender As Object, e As EventArgs) Handles CmdClearObTwo.Click
    30. Me.Invalidate(rect2)
    31. FlagCmdScaleT = False
    32. End Sub
    33. End Class


    Viele Grüße,
    Duster
    jo - wird ja langsam was.
    Und was es auch wird: Kompliziert - oder?
    Du hast da jetzt 2 Flags rumfahren, 2 Rectangles, und 4 Buttons - und können tuts kaum mehr als "piep" sagn.
    Jetzt stell dir mal vor, du willst mit der Maus ein Rectangle anfassen und verschieben können - wieviel Code da wohl ins Form purzeln wird.
    Oder willst mal 2 Rectangles, mal 15...

    Da kommt jetzt objektorientierte Programmierweise ins Spiel:
    Du kannst dir nämlich eine Figur-Klasse programmieren, die alle diese Dinge selber kann: sich zeichnen, seine Position verändern, Farbe, Stiftbreite, Füllmodus, sich auf "hide" setzen, etc.
    Das kommt alles in eine Klasse, und im Form gibts nur noch eine Liste dieser Objekte, und nicht mehr haufenweise Deklarationen im Oberen Bereich des FormCodes.
    Wenn du 3 Rechtecke willst, tust du einfach ein drittes in genannte Liste, ...

    Gugge diese Tutorial: OwnerDrawing
    @ErfinderDesRades
    Naja, kann ich nicht so wirklich einschätzen. Mit den anderen Kapiteln war ich von der Verständlichkeit her zufrieden.
    Hab aber schon oft in Tutorials gelesen dass CreateGraphics() gemieden werden sollte!

    Kennst Du bessere Bücher die sich mit VB allgemein und mit dem GDI/ GDI+ im Speziellen oder nur mit VB bzw. nur mit dem GDI/ GDI+ beschäftigen die Du empfehlen kannst?
    Die Tutorials hier im Forum (einschließlich Deinen) sind schon gebookmarked ;) !

    Der Doberenz/ Gewinnus schein halt ein Standardwerk zu sein drum hab ich Ihn gekauft!


    Viele Grüße,
    Duster

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

    ich empfehle immer gerne Löffelmann, und da besonders die "alte" 2005er Ausgabe, wo die Grundlagen am besten durchgenommen werden.
    Alle spätere Weiter-Entwicklung von vb.net und c# baut auf diesen Grundlagen auf, und ist auch überhaupt nur damit verständlich.
    Betätige mal die Foren-Suche, und guck die Treffer durch.
    Weils so alt ist, sind vermutlich einige Empfehlungs-Links verwaist.
    Der Autor Löffelmann ist auch (seit relativ kurzem) vbParadise-Member, und hat mindestens einen ganz netten Thread gestartet.

    oder Kühnel/Leibhard.

    Vlt. zuerst in Entwickler-Ressourcen und Tools, Bücher und WebCasts gucken.

    Jo, und zu OwnerDrawing empfehle ich dir dann tatsächlich meine Tutorials (bescheiden-zu-Boden-blick).
    Ich hätte nicht selbst so viel darüber geschrieben, wenn ich im INet was brauchbares dazu gefunden hätte.

    Ach - ich hab auch mal einen Komplett-Lernplan aufgestellt - Bücher lesen ist ja nur ein "Input-Kanal" von mehreren: Datenverarbeitungs-Vorraussetzungen
    Nachwievor denke ich, die dort empfohlene Vorgehensweise ist eine der schnellsten zur Entwicklung von Programmierer-Skills.
    Klaus loeffelmann hat auch hier im Forum einen Beitrag erstellt und sein Buch VB. NET 2010 online gestellt inklusive der Beispiel Daten.
    Such mal hier im forum danach.

    Edit: hier hab gefunden.
    Open-sourcen der Buchbeispiele vom Löffelmann
    Rechtschreibfehler betonen den künstlerischen Charakter des Autors.