Drawing und Select Case

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

Es gibt 33 Antworten in diesem Thema. Der letzte Beitrag () ist von Dksksm.

    Drawing und Select Case

    Moin moin

    Habe hier ein Problem mit Drawing und Select Case...
    In der Select Anweisung bekomme ich den Fehler. Ohne klappt es.


    Fehlermeldung: Der Objektverweis wurde nicht auf eine Objektinstanz festgelegt.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Imports System.Drawing
    3. Public Class drawClass
    4. Public g As Graphics
    5. Public _fform As Form
    6. #Region "Retangle Draw Form"
    7. Public Sub drawretangle(ByVal _form As String)
    8. ' in der Case funktioniert es nicht. Fehler..
    9. Select Case _form
    10. Case "main"
    11. _fform = frm_main
    12. Dim g As Graphics = frm_main.CreateGraphics
    13. Case "settings"
    14. _fform = frm_settings
    15. Dim g As Graphics = frm_settings.CreateGraphics
    16. End Select
    17. ' Das funktioniert.
    18. _fform = frm_main
    19. Dim g As Graphics = _fform.CreateGraphics
    20. Dim newPen As Penn
    21. newPen = New Pen(Color.FromArgb(255, 10, 10, 10), 6)
    22. g.DrawRectangle(newPen, New Rectangle(New Point(0, 0), New Size(_fform.Width, _fform.Height))) 'Hier bricht es ab
    23. End Sub
    24. #End Region
    25. 'Das frm_main-form:
    26. Private Sub frm_main_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    27. drawClass.drawretangle("main")
    28. End Sub

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

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

    Naja, mir fällt jetzt kein Fall, bei dem ich CreateGraphics verwende. Im Paint-EventHandler wovonauchimmer wird mit dem Parameter e auch immer ein Graphics-Objekt mitgeliefert, welches man nutzt.
    Du hast g in Zeile#6, #18, #21, #28 als je eigenständige Variablen definiert. Nicht so sinnvoll. in den letzten 3 genannten Zeilen solltest Du das Dim und As Graphics weglassen, um keine Neudeklaration zu haben, dann sollte klappen, was (immer) Du (auch) vorhast.
    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.
    @VaporiZed


    Also habe etwas geändert und folgendes resultat.
    frm_main geht auf und es wird gezeichnet.
    klicke ich auf den Button um frm_settings zu öffnen, geht diese auf aber ohne Zeichnung.
    In der Case-Anweisung kommt das Prog auch da an.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public g As Graphics
    2. Public _fform As Form
    3. #Region "Retangle Draw Form"
    4. Public Sub drawretangle(ByVal _form As String)
    5. Select Case _form
    6. Case "main"
    7. 'Das funktioniert, wird gezeichnet.
    8. _fform = frm_main
    9. Case "settings"
    10. ' kommt hier an aber es wird nicht gezeichnet.
    11. _fform = frm_settings
    12. End Select
    13. Dim g As Graphics = _fform.CreateGraphics
    14. Dim newPen As Pen
    15. newPen = New Pen(Color.FromArgb(255, 10, 10, 10), 6)
    16. g.DrawRectangle(newPen, New Rectangle(New Point(0, 0), New Size(_fform.Width, _fform.Height)))
    17. newPen = New Pen(Color.FromArgb(255, 90, 90, 90), 20)
    18. g.DrawLine(newPen, 10, 22, _fform.Width - 7, 22)
    19. newPen = New Pen(Color.FromArgb(255, 90, 90, 90), 10)
    20. g.DrawRectangle(newPen, New Rectangle(New Point(7, 7), New Size(_fform.Width - 14, _fform.Height - 14)))
    21. newPen = New Pen(Color.FromArgb(255, 130, 130, 130), 2)
    22. g.DrawRectangle(newPen, New Rectangle(New Point(13, 31), New Size(_fform.Width - 26, _fform.Height - 44)))
    23. End Sub
    24. #End Region
    25. ' Aufruf aus frm_main
    26. Private Sub llbl_sets_Click(sender As Object, e As EventArgs) Handles llbl_sets.Click
    27. Using frm As New frm_settings()
    28. frm.ShowDialog(Me)
    29. End Using
    30. End Sub
    31. 'Aufruf aus frm_settings
    32. Private Sub frm_settings_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    33. drawClass.drawretangle("settings")
    34. End Sub

    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @Amelie Das ganze ist ein Fehl-Design.
    Mach Dir eine Draw-Methode, der Du die Graphics-Instanz selbst mitgibst, nicht aber den Namen der Form.
    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!
    @Amelie So was:

    VB.NET-Quellcode

    1. Public Sub drawretangle(ByVal g As Graphics)
    2. ' ...
    3. 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!
    @RodFromGermany

    So habe nun mal gegoogle usw.. Wieder nichts für mich gefunden was mich weiter bringt. Da werden immer Linien auf PictureBoxen gemalt grr....
    Bitte hilf mir mal an einem Beispiel, wie ich das anstellen kann.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    @ErfinderDesRades
    Darum gehts nicht.
    Auf der frm_main wird ja alles richtig gezeichnet, so wie ich es mir vorstellte.
    Was nicht Klappt ist die Select Case Auswahl.
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

    Amelie schrieb:

    Was nicht Klappt ist die Select Case Auswahl.
    Wenn Du gie Graphics-Instanz übergibst, ist Dein Select Case oben obsolete.
    Wenn, dann musst Du einen weiteren Kennungs-Parameter übergeben, den Du mit Select Case abfragen kannst.
    Was genau willst Du erreichen?
    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!

    Amelie schrieb:

    Auf der frm_main wird ja alles richtig gezeichnet, so wie ich es mir vorstellte.
    was ich von deim Code gesehe habe, lässt mich vermuten, dass auch frmMain buggy gemalt wird.

    Folgendes Experiment:
    Öffne frmMain - dann erscheint ja die Zeichnung - oder?
    Dann frmMain minimieren, und anschliessend wieder herstellen.
    Nach dem wie der hier gezeigte Code aussieht, vermute ich, dass dann die Zeichnung auch auf frmMain weg ist.
    probierma

    Amelie schrieb:

    Select Case _form
    Case "main"
    _fform = frm_main
    Dim g As Graphics = frm_main.CreateGraphics
    Case "settings"
    _fform = frm_settings
    Dim g As Graphics = frm_settings.CreateGraphics
    End Select


    Amelie schrieb:

    _fform = frm_main
    Dim g As Graphics = _fform.CreateGraphics


    Sollte in der Select Case Anweisung frm_main nicht _fform sein?
    Also das zeichnet beim starten und nach dem minimieren ist auch alles wieder gezeichnet.

    VB.NET-Quellcode

    1. Public g As Graphics
    2. Public _fform As Form
    3. #Region "Retangle Draw Form"
    4. Public Sub draw()
    5. Dim g As Graphics = _fform.CreateGraphics
    6. Dim newPen As Pen
    7. newPen = New Pen(Color.FromArgb(255, 10, 10, 10), 6)
    8. g.DrawRectangle(newPen, New Rectangle(New Point(0, 0), New Size(_fform.Width, _fform.Height)))
    9. newPen = New Pen(Color.FromArgb(255, 90, 90, 90), 20)
    10. g.DrawLine(newPen, 10, 22, _fform.Width - 7, 22)
    11. newPen = New Pen(Color.FromArgb(255, 90, 90, 90), 10)
    12. g.DrawRectangle(newPen, New Rectangle(New Point(7, 7), New Size(_fform.Width - 14, _fform.Height - 14)))
    13. newPen = New Pen(Color.FromArgb(255, 130, 130, 130), 2)
    14. g.DrawRectangle(newPen, New Rectangle(New Point(13, 31), New Size(_fform.Width - 26, _fform.Height - 44)))
    15. End Sub
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:
    Und wenn was an den Formgrößen gemacht wird? Wird's wieder doof aussehen, weil dann die Zeichnungen abgeschnittewn werden. Das Zeichnen kann ja gerne in einer gemeinsamen Methode codetechnisch abgearbeitet werden. Aber das "Startsignal" sollte das Paint-Event der Forms sein. Die geben dann gleich ihr Graphics-Objekt mit, dann muss auch keins extra erstellt werden.
    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.
    Mir fallen auf Anhieb 3 Varianten ein:
    1. Eine Shared Sub in der Hauptformklasse, die vom Haupt-, aber auch vom Subform aufgerufen werden kann.

    VB.NET-Quellcode

    1. Friend Shared Sub DrawCanvasContent(_fform As Form, g As Graphics)
    2. 'hier Dein Code wie bisher, aber eben ohne Dim g As Graphics = _fform.CreateGraphics
    3. End Sub

    Das wird dann in den Forms so aufgerufen:

    VB.NET-Quellcode

    1. Private Sub FrmMain_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    2. DrawCanvasContent.Draw(Me, e.Graphics)
    3. 'bzw im Subform
    4. FrmMain.DrawCanvasContent.Draw(Me, e.Graphics)
    5. End Sub


    2. Die Forms könnten eine gemeinsame Basisklasse haben, die in ihrem Paint-EventHandler einfach Deinen bisherigen Code ausführt. Dann schreibt man in den Paint-EventHandlers der Forms nur MyBase.Paint(sender, e).

    3. Man erzeugt eine extra Klasse X, die den Malcode beinhaltet. Man lagert also den Code aus. Und ruft in den Paint-EventHandler der Forms jene Klasse bzw. dessen Methode auf, die für das Zeichnen zuständig ist. Dabei könnte jedes Form seine eigene X-Instanz erzeugen oder man gibt die X-Instanz vom Hauptform an die Subforms weiter.

    Probier es aus. Mal sehen, was Dir am meisten zusagt.
    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.

    Amelie schrieb:

    Das bei jeder Form die geöffnet wird die Draw ausgefürt werden.
    Gib allen Formen eine gemeinsame Basisklasse (statt Inherits Form machst Du Inherits MyBaseClass in den Designer-Dateien der Form und dann so was:

    VB.NET-Quellcode

    1. Partial Class Form2
    2. Inherits MyBaseClass 'System.Windows.Forms.Form
    3. ' ...
    4. End Class

    VB.NET-Quellcode

    1. Public Class MyBaseClass
    2. Inherits Form
    3. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    4. MyBase.OnPaint(e)
    5. If TypeOf (Me) Is Form1 Then
    6. e.Graphics.FillEllipse(Brushes.Red, New Rectangle(Point.Empty, Me.ClientSize))
    7. ElseIf TypeOf (Me) Is Form2 Then
    8. e.Graphics.FillEllipse(Brushes.Green, New Rectangle(Point.Empty, Me.ClientSize))
    9. End If
    10. End Sub
    11. 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!
    @VaporiZed
    @RodFromGermany
    Moin moin,

    Ich habe nun diese Variante gewählt. Scheint nach den ersten Test gut zu funktionieren.
    Danke für die Unterstützung. ;)


    Spoiler anzeigen

    VB.NET-Quellcode

    1. 'Das Form, ein TEST-Form
    2. Public Class frm_test
    3. Dim MyApp As New MyApp
    4. Dim drawClass As New drawClass
    5. Private Sub frm_test_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    6. 'todo
    7. End Sub
    8. Private Sub frm_test_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    9. drawClass.DrawCanvasContent(Me, e.Graphics)
    10. End Sub
    11. End Class


    VB.NET-Quellcode

    1. 'Die Class
    2. Imports System.Drawing.Drawing2D
    3. Imports System.Drawing
    4. Public Class drawClass
    5. #Region "Retangle Draw Form"
    6. Public Sub DrawCanvasContent(_fform As Form, g As Graphics)
    7. g = _fform.CreateGraphics
    8. Dim newPen As Pen
    9. newPen = New Pen(Color.FromArgb(255, 10, 10, 10), 6)
    10. g.DrawRectangle(newPen, New Rectangle(New Point(0, 0), New Size(_fform.Width, _fform.Height)))
    11. newPen = New Pen(Color.FromArgb(255, 90, 90, 90), 20)
    12. g.DrawLine(newPen, 10, 22, _fform.Width - 7, 22)
    13. newPen = New Pen(Color.FromArgb(255, 90, 90, 90), 10)
    14. g.DrawRectangle(newPen, New Rectangle(New Point(7, 7), New Size(_fform.Width - 14, _fform.Height - 14)))
    15. newPen = New Pen(Color.FromArgb(255, 130, 130, 130), 2)
    16. g.DrawRectangle(newPen, New Rectangle(New Point(13, 31), New Size(_fform.Width - 26, _fform.Height - 44)))
    17. End Sub
    18. #End Region



    So schaut es dann aus ;)
    Bilder
    • testform-1.jpg

      28,86 kB, 400×243, 44 mal angesehen
    Asperger Autistin. Brauche immer etwas um gewisse Sachen zu verstehen. :huh:

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

    Nix mit CreateGraphics. Dafür hast Du doch den Parameter g! In dieser Zeile wird der DrawCanvasContent-Methode bereits ein existierendes Graphics-Objekt mitgegeben.
    Pens sind Typen, die disposed werden sollten. Da DrawCanvasContent konsequenterweise unzählige Male aufgerufen wird, könnte das auf Dauer ziemliche Ressourcenverschwendung mit den Pens werden. Erzeuge sie nur einmal, und zwar entweder außerhalb der Methoden oder innerhalb des Konstruktors. Und am Ende des Programms die Pens mit der CleanUp-Methode entsorgen:

    VB.NET-Quellcode

    1. Public Class drawClass
    2. Private ReadOnly Pen1 As New Pen(Color.FromArgb(255, 10, 10, 10), 6)
    3. Private ReadOnly Pen2 As New Pen(Color.FromArgb(255, 90, 90, 90), 20)
    4. Private ReadOnly Pen3 As New Pen(Color.FromArgb(255, 90, 90, 90), 10)
    5. Private ReadOnly Pen4 As New Pen(Color.FromArgb(255, 130, 130, 130), 2)
    6. #Region "Retangle Draw Form"
    7. Public Sub DrawCanvasContent(_fform As Form, g As Graphics)
    8. 'g = _fform.CreateGraphics - hinfort damit!
    9. g.DrawRectangle(Pen1, New Rectangle(New Point(0, 0), New Size(Form.Width, Form.Height)))
    10. g.DrawLine(Pen2, 10, 22, Form.Width - 7, 22)
    11. g.DrawRectangle(Pen3, New Rectangle(New Point(7, 7), New Size(Form.Width - 14, Form.Height - 14)))
    12. g.DrawRectangle(Pen4, New Rectangle(New Point(13, 31), New Size(Form.Width - 26, Form.Height - 44)))
    13. End Sub
    14. Friend Sub CleanUp()
    15. Pen1.Dispose()
    16. Pen2.Dispose()
    17. Pen3.Dispose()
    18. Pen4.Dispose()
    19. End Sub
    Noch besser wär zwar die Implementierung von IDisposable, aber das hier reicht auch für Anfang.
    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.