GDI+ stürzt ab bei Doublebufferd (Fehlermeldung = Exception, nicht mehr) und flackert ohne

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von us4711.

    GDI+ stürzt ab bei Doublebufferd (Fehlermeldung = Exception, nicht mehr) und flackert ohne

    Hallo an alle,

    ich versuche mich gerade mal testweise an einer eigenen Progressbar, und nach allem was ich so gelesen habe ist gdi+ natürlich die Wahl der Qual geworden,
    aber es flackert halt mal richtig heftig wenn ich was zeichne, also dachte ich mir klar hau den Doublebuffer rein, aber egal wie ich dies mache (ob im designer die Option setzen, oder per Code)
    stürzt bei aktivem DB mein Prog einfach ab... und die genialste Fehlermeldung der Welt "exception" erscheint...

    der Code mit dem ich zu zeichnen versuche:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class GradientPbar
    2. #Region "Deklaration"
    3. Private G As Graphics
    4. Private ValueVal As Double = 50
    5. Private MinVal As Double = 0
    6. Private MaxVal As Double = 100
    7. Private WithLabelVal As Boolean = False
    8. Private GlossyVal As Boolean = True
    9. Private RoundedVal As Boolean = True
    10. Private LabelColorVal As Color = Color.Black
    11. Private TopColorVal As Color = Color.DarkRed
    12. Private BotColorVal As Color = Color.Black
    13. Private GlossColorVal As Color = Color.White
    14. Dim lgbbrush As LinearGradientBrush
    15. #End Region
    16. Public Property Value As Double
    17. Get
    18. Return ValueVal
    19. End Get
    20. Set(value As Double)
    21. Me.ValueVal = value
    22. Me.Invalidate()
    23. End Set
    24. End Property
    25. Public Property Minimum As Double
    26. Get
    27. Return Me.MinVal
    28. End Get
    29. Set(value As Double)
    30. Me.MinVal = value
    31. End Set
    32. End Property
    33. Public Property Maximum As Double
    34. Get
    35. Return Me.MaxVal
    36. End Get
    37. Set(value As Double)
    38. Me.MaxVal = value
    39. End Set
    40. End Property
    41. Protected Overrides Sub OnResize(ByVal e As EventArgs)
    42. Me.Invalidate()
    43. End Sub
    44. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    45. G = e.Graphics
    46. 'With G
    47. ' '.CompositingQuality = CompositingQuality.HighQuality
    48. ' '.InterpolationMode = InterpolationMode.HighQualityBicubic
    49. 'End With
    50. Dim rect As Rectangle = Me.ClientRectangle
    51. lgbbrush = New LinearGradientBrush(rect, TopColorVal, BotColorVal, LinearGradientMode.Vertical)
    52. Dim percent As Decimal = CDec((Value - MinVal) / (MaxVal - MinVal))
    53. rect.Width = CInt(rect.Width * percent)
    54. G.FillRectangle(lgbbrush, rect)
    55. lgbbrush.Dispose()
    56. G.Dispose()
    57. End Sub
    58. End Class



    weiss evtl. jemand rat ?

    Greets

    Edit:

    Hab jetzt testweise mal ein neues Project aufgemacht und da wieder ein Benutzersteuerelement hinzugefügt, DB aktiviert, und schwups ich kann es nicht mal mehr auf die Form ziehen da Sonst wieder ein Fehler kommt, er Meckert dabei ungültiger Parameter, aber eben nur wenn DB aktiv ist....
    Ist das wieder was wo Microsoft versaut hat in Win 10 ?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

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

    Wenn ich Deinen Code als Teil meiner WinForm nehme, läuft alles rund.
    Wenn DoubleBuffering eingeschaltet ist: ja, dann kommt der Crash. Liegt an dem Disposen von G in Zeile 75. Kannst Du das nicht zum Ende Deines Programms erst machen? Und irgendwo hab ich gehört (ok, gelesen), dass Du lgbrush auch mit nem Using-Block verbinden kannst. Soll wohl sauberer sein und das Dispose ersparen.
    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.
    Der Code durefte auch nicht funktionieren. Wer oder was stellt hier ClientRectangle zur verfuegung? Hast du vllt. vergessen von Control erben zu lassen? Noch dazu, was wenn Value < Minimum oder Value > Maximum? Ich kann Maximum bei 100 haben und einen Wert von 100000 setzen? Sollte eine Exception geworfen werden, oder automatisch Minimum = Minimum gesetzt, bzw. halt mit Maximum.
    And i think to myself... what a wonderfuL World!
    @Eddy naja zum einen hab ich den Code aus einem der Ersten google ergebnisse zu (gdi+ Progressbar) daher ist er sicher nicht perfekt, und es geht mir aktuell ja um das herumtesten mit GDI+ hab bisher eig. nur normale Formsanwendungen benutzt , und ClientRectangle hat doch ein Me. davor also schätz ich mal von der Größe des Usercontrol ?

    @VaporiZed ich seh grad leider nicht wie ich das in nen UsingBlock packen könnte ?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    VB.NET-Quellcode

    1. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    2. G = e.Graphics
    3. Dim rect As Rectangle = Me.ClientRectangle
    4. Using lgbbrush = New LinearGradientBrush(rect, TopColorVal, BotColorVal, LinearGradientMode.Vertical)
    5. Dim percent As Decimal = CDec((Value - MinVal) / (MaxVal - MinVal))
    6. rect.Width = CInt(rect.Width * percent)
    7. G.FillRectangle(lgbbrush, rect)
    8. End Using
    9. End Sub

    Aber der Using-Block ist jetzt erstmal wurscht. G zu disposen ist an der Stelle der Fehlerauslöser. Das ist das einzig relevante.
    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.

    VB.NET-Quellcode

    1. Using G As Graphics = e.Graphics


    Das ist ueberfluessig,

    VB.NET-Quellcode

    1. Protected Overrides Sub OnResize(ByVal e As EventArgs)
    2. Me.Invalidate()
    3. End Sub


    wenn du deisen Style setzt:
    ControlStyles.ResizeRedraw, True


    Wobei bei mir hat das G.Dispose keinen Fehler verursacht, VS2010 und VS2013.
    And i think to myself... what a wonderfuL World!
    @Eddy Inherits Control markiert er mir direkt rot "Die für GradientPbar festgelegte Control-Basisklasse darf sich bnicht von der UserControl-Basisklasse eines ihrer anderen partiellen Typen unterscheioden." <- was auch immer das heissen soll,

    VB.NET-Quellcode

    1. SetStyle(ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint Or ControlStyles.ResizeRedraw, True)

    wieso "Or" sollen denn nicht alle gesetzt werden ?

    G hab ich jetzt weggelassen und direlkt e.Graphics benutzt
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Unter VS2017CE kommt bei mir mit der e.Graphics.Dispose-Zeile zumindest ne betitelte Exception. Ohne die Zeile läuft es.
    @asusdk: Weil man da binär denken muss.
    Bilder
    • eGraphicsDispose.png

      14,07 kB, 1.039×316, 78 mal angesehen
    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.
    also mit:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class GradientPbar
    2. #Region "Deklaration"
    3. Private ValueVal As Double = 50
    4. Private MinVal As Double = 0
    5. Private MaxVal As Double = 100
    6. Private WithLabelVal As Boolean = False
    7. Private GlossyVal As Boolean = True
    8. Private RoundedVal As Boolean = True
    9. Private LabelColorVal As Color = Color.Black
    10. Private TopColorVal As Color = Color.DarkRed
    11. Private BotColorVal As Color = Color.Black
    12. Private GlossColorVal As Color = Color.White
    13. #End Region
    14. Sub New()
    15. SetStyle(ControlStyles.OptimizedDoubleBuffer Or ControlStyles.UserPaint Or ControlStyles.ResizeRedraw, True)
    16. End Sub
    17. Public Property Value As Double
    18. Get
    19. Return ValueVal
    20. End Get
    21. Set(ByVal value As Double)
    22. Me.ValueVal = value
    23. Me.Invalidate()
    24. End Set
    25. End Property
    26. Public Property Minimum As Double
    27. Get
    28. Return Me.MinVal
    29. End Get
    30. Set(ByVal value As Double)
    31. Me.MinVal = value
    32. End Set
    33. End Property
    34. Public Property Maximum As Double
    35. Get
    36. Return Me.MaxVal
    37. End Get
    38. Set(ByVal value As Double)
    39. Me.MaxVal = value
    40. End Set
    41. End Property
    42. Protected Overrides Sub OnResize(ByVal e As EventArgs)
    43. Me.Invalidate()
    44. End Sub
    45. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    46. Dim rect As Rectangle = Me.ClientRectangle
    47. Using lgbbrush As New LinearGradientBrush(rect, TopColorVal, BotColorVal, LinearGradientMode.Vertical)
    48. Dim percent As Decimal = CDec((Value - MinVal) / (MaxVal - MinVal))
    49. rect.Width = CInt(rect.Width * percent)
    50. e.Graphics.FillRectangle(lgbbrush, rect)
    51. End Using
    52. End Sub
    53. End Class


    flackert es wieder, trotz jetzt dank euch funktionierendem DB

    mit :

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class GradientPbar
    2. #Region "Deklaration"
    3. Private ValueVal As Double = 50
    4. Private MinVal As Double = 0
    5. Private MaxVal As Double = 100
    6. Private WithLabelVal As Boolean = False
    7. Private GlossyVal As Boolean = True
    8. Private RoundedVal As Boolean = True
    9. Private LabelColorVal As Color = Color.Black
    10. Private TopColorVal As Color = Color.DarkRed
    11. Private BotColorVal As Color = Color.Black
    12. Private GlossColorVal As Color = Color.White
    13. Dim lgbbrush As LinearGradientBrush
    14. #End Region
    15. Public Property Value As Double
    16. Get
    17. Return ValueVal
    18. End Get
    19. Set(value As Double)
    20. Me.ValueVal = value
    21. Me.Invalidate()
    22. End Set
    23. End Property
    24. Public Property Minimum As Double
    25. Get
    26. Return Me.MinVal
    27. End Get
    28. Set(value As Double)
    29. Me.MinVal = value
    30. End Set
    31. End Property
    32. Public Property Maximum As Double
    33. Get
    34. Return Me.MaxVal
    35. End Get
    36. Set(value As Double)
    37. Me.MaxVal = value
    38. End Set
    39. End Property
    40. Protected Overrides Sub OnResize(ByVal e As EventArgs)
    41. Me.Invalidate()
    42. End Sub
    43. Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    44. Dim rect As Rectangle = Me.ClientRectangle
    45. lgbbrush = New LinearGradientBrush(rect, TopColorVal, BotColorVal, LinearGradientMode.Vertical)
    46. Dim percent As Decimal = CDec((Value - MinVal) / (MaxVal - MinVal))
    47. rect.Width = CInt(rect.Width * percent)
    48. e.Graphics.FillRectangle(lgbbrush, rect)
    49. lgbbrush.Dispose()
    50. End Sub
    51. Public Sub New()
    52. Dieser Aufruf ist für den Designer erforderlich.
    53. InitializeComponent()
    54. Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    55. Me.UpdateStyles()
    56. Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
    57. End Sub
    58. End Class

    läuft es butterweich =)

    @Eddy
    Wobei bei mir hat das G.Dispose keinen Fehler verursacht, VS2010 und VS2013.

    Ich nutze aktuell schon das 2017er

    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Fehler hin oder her - Logik verbietet das Disposen von e.Graphics:
    Du hast dieses Objeckt nicht erstellst, dann darfst du es auch nicht vernichten - du weißt ja nicht, obs nicht woanners noch gebraucht wird.

    anders beim LinearGradientBrush: Den erstellst du - also räum ihn auch bitte wiederauf, wenn du ihn nicht mehr brauchst.