Graphics.Save() & .Restore(GraphicState) / wie geht das?

  • VB.NET

Es gibt 3 Antworten in diesem Thema. Der letzte Beitrag () ist von NoIde.

    Graphics.Save() & .Restore(GraphicState) / wie geht das?

    Hallo!

    ​Ich bin gerade dabei ein Control nach meinen Bedürfnissen anzupassen.
    Und zwar geht es um ein MonthCalendar!
    Da habe ich jetzt ein Override beim OnMouseDown angelegt und wollte das markieren des geklickten Datums umgehen.

    ​Ich möchte den Ur-Zustand des Controls speichern, dann ein Datum mit einem FillRectangle markieren und beim klick auf ein anderes Datum den Ur-Zustand wieder herstellen und das neue Datum "bemalen"!

    Das bemalen klappt, aber das wiederherstellen nicht!

    ​Ich hab das "GraphicState" in einer GraphicState Variablen gespeichert aber bei g.restore(GraphicState) passiert nichts!

    Hier mein Code, jedoch habe ich ein anderes Control als das vom Standard-Katalog weswegen der Code bei Euch so nicht laufen wird!:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private _graphics As Graphics
    2. Private _prevGraphics As GraphicsState
    3. Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
    4. If (e.Button = MouseButtons.Left) Then
    5. _graphics = Me.CreateGraphics
    6. _prevGraphics = _graphics.Save()
    7. Dim cursorPosition As Point = e.Location
    8. Debug.WriteLine(cursorPosition)
    9. Dim hti As MonthViewDay = HitTest(cursorPosition)
    10. Debug.WriteLine(hti.Date)
    11. Dim _brush As SolidBrush = New SolidBrush(Color.FromArgb(20, 80, 80, 80))
    12. _graphics.FillRectangle(_brush, hti.Bounds)
    13. _graphics.Restore(_prevGraphics)
    14. End If
    15. _graphics.Restore(_prevGraphics)
    16. Return
    17. End Sub
    Die GraphicsState-Klasse ist kein Abbild von dem gezeichneten. Vielmehr stellt sie den "Zustand" eine Graphics-Objektes dar. Du hast ja einige Properties wie z.B. Graphics.SmoothingMode, stellst du den auf SmoothingMode.AntiAlias und speicherst, ist das in dem Zustand gespeichert.

    Siehe wie hier die erste Ellipse mit SmoothingMode.AntiAlias.Default gemalt wird, die "Einstellung" restored, dann die zweite Ellipse mit SmoothingMode.AntiAlias gezeichnet wird.

    VB.NET-Quellcode

    1. Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    2. e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
    3. Dim gs As GraphicsState = e.Graphics.Save()
    4. e.Graphics.SmoothingMode = SmoothingMode.Default
    5. e.Graphics.FillEllipse(New SolidBrush(Color.Blue), 0, 0, 100, 100)
    6. e.Graphics.Restore(gs)
    7. e.Graphics.FillEllipse(New SolidBrush(Color.Blue), 100, 0, 100, 100)
    8. End Sub


    Zudem würde ich auf CreateGraphics verzichten, an das Graphics-Objekt kommst du durch Paint-Event des Controls.
    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin
    Also wenn man da so rummahlt, ist das was als erstes gemalt wird immer hinter dem neuen, also im Hintergrund. Also Grundsätzlich zeichne ich Controls in einer standart-variante, dazu optional bzw. bedingt besondere Zustände. Wobei bei änderung eines Zustandes auch neu gemahlt werden muss. Wenn nur Teil neu gezeichnet werden muss, kann man auch noch nur diesen Bereich neu zeichnen, spart ein wenig Zeit ein. Schau dir die überladungen von Control.Invalidate an.

    VB.NET-Quellcode

    1. Public Class Class1
    2. Inherits Control
    3. Private _checked As Boolean
    4. Public Property Checked As Boolean
    5. Get
    6. Return _checked
    7. End Get
    8. Set(ByVal value As Boolean)
    9. If _checked <> value Then
    10. _checked = value
    11. Invalidate()
    12. End If
    13. End Set
    14. End Property
    15. Private Sub Class1_MouseClicks(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick, Me.MouseDoubleClick
    16. Checked = Not Checked
    17. End Sub
    18. Private Sub Class1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    19. e.Graphics.FillRectangle(Brushes.Blue, ClientRectangle)
    20. If Checked Then
    21. e.Graphics.FillEllipse(Brushes.Yellow, ClientRectangle)
    22. End If
    23. End Sub
    24. End Class

    Cloud Computer? Nein Danke! Das ist nur ein weiterer Schritt zur totalen Überwachung.
    „Wer die Freiheit aufgibt, um Sicherheit zu gewinnen, wird am Ende beides verlieren.“
    Benjamin Franklin