Vor-und/oder-Nachteile (GDI+) e.Graphics VS GraphicsfromImage

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

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

    Vor-und/oder-Nachteile (GDI+) e.Graphics VS GraphicsfromImage

    Hallo Ihr Lieben,

    Ich habe mal eine kleine Grundsatzfrage und hoffe das ich im richtigen Teil des Forums poste ^^

    Ich habe einen Button per GDI+ erstellt, dabei ist mir eine Grundsatzfrage aufgekommen, ist es "besser" direkt mit e.Graphics zu arbeiten, oder sollte man lieber ein eigenes Graphics Object verwenden ?


    Kompletter Code des Buttons wie ich Ihn Aktuell verwende:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class DKButton
    2. Private MouseState As Helpers.MouseState = Helpers.MouseState.None
    3. Public Sub New()
    4. InitializeComponent()
    5. Me.SetStyle(ControlStyles.OptimizedDoubleBuffer Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint, True)
    6. DoubleBuffered = True
    7. Me.UpdateStyles()
    8. End Sub
    9. Dim _BackGroundColor As Color = Color.DarkGray
    10. Public Property BackGroundColor As Color
    11. Get
    12. Return _BackGroundColor
    13. End Get
    14. Set(value As Color)
    15. _BackGroundColor = value
    16. Invalidate()
    17. End Set
    18. End Property
    19. Dim _HoverColor As Color = Color.DimGray
    20. Public Property HoverColor As Color
    21. Get
    22. Return _HoverColor
    23. End Get
    24. Set(value As Color)
    25. _HoverColor = value
    26. Invalidate()
    27. End Set
    28. End Property
    29. Dim _ClickColor As Color = Color.OrangeRed
    30. Public Property ClickColor As Color
    31. Get
    32. Return _ClickColor
    33. End Get
    34. Set(value As Color)
    35. _ClickColor = value
    36. Invalidate()
    37. End Set
    38. End Property
    39. Dim _TextColor As Color = Color.White
    40. Public Property TextColor As Color
    41. Get
    42. Return _TextColor
    43. End Get
    44. Set(value As Color)
    45. _TextColor = value
    46. Invalidate()
    47. End Set
    48. End Property
    49. Dim _TextFont As Font = Font
    50. Public Property TextFont As Font
    51. Get
    52. Return _TextFont
    53. End Get
    54. Set(value As Font)
    55. _TextFont = value
    56. Invalidate()
    57. End Set
    58. End Property
    59. Dim _ButtonText As String = "X"
    60. Public Property ButtonText As String
    61. Get
    62. Return _ButtonText
    63. End Get
    64. Set(value As String)
    65. _ButtonText = value
    66. Invalidate()
    67. End Set
    68. End Property
    69. Dim _Border As Boolean = True
    70. Property Border As Boolean
    71. Get
    72. Return _Border
    73. End Get
    74. Set(value As Boolean)
    75. _Border = value
    76. Invalidate()
    77. End Set
    78. End Property
    79. Dim _BorderColor As Color = Color.Black
    80. Public Property BorderColor As Color
    81. Get
    82. Return _BorderColor
    83. End Get
    84. Set(value As Color)
    85. _BorderColor = value
    86. Invalidate()
    87. End Set
    88. End Property
    89. Dim _Hatch As Boolean = True
    90. Property Hatch As Boolean
    91. Get
    92. Return _Hatch
    93. End Get
    94. Set(value As Boolean)
    95. _Hatch = value
    96. Invalidate()
    97. End Set
    98. End Property
    99. Dim _HatchColor As Color = Color.Gray
    100. Property HatchColor As Color
    101. Get
    102. Return _HatchColor
    103. End Get
    104. Set(value As Color)
    105. _HatchColor = value
    106. Invalidate()
    107. End Set
    108. End Property
    109. Dim _GlassEffect As Boolean = True
    110. Property GlassEffect As Boolean
    111. Get
    112. Return _GlassEffect
    113. End Get
    114. Set(value As Boolean)
    115. _GlassEffect = value
    116. Invalidate()
    117. End Set
    118. End Property
    119. Dim _GlassEffectColor As Color = Color.White
    120. Property GlassEffectColor As Color
    121. Get
    122. Return _GlassEffectColor
    123. End Get
    124. Set(value As Color)
    125. _GlassEffectColor = value
    126. Invalidate()
    127. End Set
    128. End Property
    129. Private Function GetTextPosition(ByVal TextSize As SizeF) As PointF
    130. Dim DrawToRect As Rectangle = New Rectangle(0, 0, Me.Width, Me.Height)
    131. Return New PointF(((DrawToRect.Width \ 2) - (CInt(TextSize.Width) \ 2)), ((DrawToRect.Height \ 2) - (CInt(TextSize.Height) \ 2)))
    132. End Function
    133. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    134. Using B As New Bitmap(Width, Height)
    135. Using G As Graphics = Graphics.FromImage(B)
    136. With G
    137. .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    138. .SmoothingMode = SmoothingMode.AntiAlias
    139. .InterpolationMode = InterpolationMode.HighQualityBicubic
    140. .CompositingQuality = CompositingQuality.HighQuality
    141. .PixelOffsetMode = PixelOffsetMode.HighQuality
    142. Dim tmp_Color As Color = Color.DarkGray
    143. Select Case MouseState
    144. Case Helpers.MouseState.None
    145. tmp_Color = _BackGroundColor
    146. Case Helpers.MouseState.Over
    147. tmp_Color = _HoverColor
    148. Case Helpers.MouseState.Pressed
    149. tmp_Color = _ClickColor
    150. End Select
    151. Using BackgroundBrush As New SolidBrush(tmp_Color)
    152. .FillRectangle(BackgroundBrush, New Rectangle(0, 0, Me.Width, Me.Height))
    153. End Using
    154. If _Hatch Then
    155. Using HatchBrush As New HatchBrush(HatchStyle.DarkDownwardDiagonal, Color.FromArgb(75, _HatchColor), Color.Transparent)
    156. .FillRectangle(HatchBrush, New Rectangle(0, 0, Me.Width, Me.Height))
    157. End Using
    158. End If
    159. If _GlassEffect Then
    160. Using GlassEffectBrush As New LinearGradientBrush(New Rectangle(0, 0, Me.Width, Me.Height \ 2), Color.FromArgb(180, _GlassEffectColor), Color.FromArgb(25, _GlassEffectColor), LinearGradientMode.Vertical)
    161. .FillRectangle(GlassEffectBrush, New Rectangle(0, 0, Me.Width, Me.Height \ 2))
    162. End Using
    163. End If
    164. If _Border Then
    165. Using BorderBrush As New SolidBrush(_BorderColor)
    166. Using BorderPen As New Pen(BorderBrush, 2)
    167. .DrawRectangle(BorderPen, New Rectangle(0, 0, Me.Width, Me.Height))
    168. End Using
    169. End Using
    170. End If
    171. Using ButtonTextBrush As New SolidBrush(_TextColor)
    172. .DrawString(ButtonText, Font, ButtonTextBrush, GetTextPosition(.MeasureString(ButtonText, Font)), StringFormat.GenericDefault)
    173. End Using
    174. End With
    175. End Using
    176. With e.Graphics
    177. .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    178. .SmoothingMode = SmoothingMode.AntiAlias
    179. .InterpolationMode = InterpolationMode.HighQualityBicubic
    180. .CompositingQuality = CompositingQuality.HighQuality
    181. .PixelOffsetMode = PixelOffsetMode.HighQuality
    182. .DrawImage(B, New PointF(0, 0))
    183. End With
    184. End Using
    185. End Sub
    186. Protected Overrides Sub OnMouseEnter(e As EventArgs)
    187. MouseState = Helpers.MouseState.Over
    188. Invalidate()
    189. MyBase.OnMouseEnter(e)
    190. End Sub
    191. Protected Overrides Sub OnMouseDown(e As MouseEventArgs)
    192. MouseState = Helpers.MouseState.Pressed
    193. Invalidate()
    194. MyBase.OnMouseDown(e)
    195. End Sub
    196. Protected Overrides Sub OnMouseLeave(e As EventArgs)
    197. MouseState = Helpers.MouseState.None
    198. Invalidate()
    199. MyBase.OnMouseEnter(e)
    200. End Sub
    201. Protected Overrides Sub OnMouseUp(e As MouseEventArgs)
    202. MouseState = Helpers.MouseState.None
    203. Invalidate()
    204. MyBase.OnMouseUp(e)
    205. End Sub
    206. End Class
    207. Public Class Helpers
    208. Public Enum MouseState
    209. None
    210. Over
    211. Pressed
    212. End Enum
    213. End Class


    Nur Paint (Eigenes Graphics Object)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    2. Using B As New Bitmap(Width, Height)
    3. Using G As Graphics = Graphics.FromImage(B)
    4. With G
    5. .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    6. .SmoothingMode = SmoothingMode.AntiAlias
    7. .InterpolationMode = InterpolationMode.HighQualityBicubic
    8. .CompositingQuality = CompositingQuality.HighQuality
    9. .PixelOffsetMode = PixelOffsetMode.HighQuality
    10. Dim tmp_Color As Color = Color.DarkGray
    11. Select Case MouseState
    12. Case Helpers.MouseState.None
    13. tmp_Color = _BackGroundColor
    14. Case Helpers.MouseState.Over
    15. tmp_Color = _HoverColor
    16. Case Helpers.MouseState.Pressed
    17. tmp_Color = _ClickColor
    18. End Select
    19. Using BackgroundBrush As New SolidBrush(tmp_Color)
    20. .FillRectangle(BackgroundBrush, New Rectangle(0, 0, Me.Width, Me.Height))
    21. End Using
    22. If _Hatch Then
    23. Using HatchBrush As New HatchBrush(HatchStyle.DarkDownwardDiagonal, Color.FromArgb(75, _HatchColor), Color.Transparent)
    24. .FillRectangle(HatchBrush, New Rectangle(0, 0, Me.Width, Me.Height))
    25. End Using
    26. End If
    27. If _GlassEffect Then
    28. Using GlassEffectBrush As New LinearGradientBrush(New Rectangle(0, 0, Me.Width, Me.Height \ 2), Color.FromArgb(180, _GlassEffectColor), Color.FromArgb(25, _GlassEffectColor), LinearGradientMode.Vertical)
    29. .FillRectangle(GlassEffectBrush, New Rectangle(0, 0, Me.Width, Me.Height \ 2))
    30. End Using
    31. End If
    32. If _Border Then
    33. Using BorderBrush As New SolidBrush(_BorderColor)
    34. Using BorderPen As New Pen(BorderBrush, 2)
    35. .DrawRectangle(BorderPen, New Rectangle(0, 0, Me.Width, Me.Height))
    36. End Using
    37. End Using
    38. End If
    39. Using ButtonTextBrush As New SolidBrush(_TextColor)
    40. .DrawString(ButtonText, Font, ButtonTextBrush, GetTextPosition(.MeasureString(ButtonText, Font)), StringFormat.GenericDefault)
    41. End Using
    42. End With
    43. End Using
    44. With e.Graphics
    45. .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    46. .SmoothingMode = SmoothingMode.AntiAlias
    47. .InterpolationMode = InterpolationMode.HighQualityBicubic
    48. .CompositingQuality = CompositingQuality.HighQuality
    49. .PixelOffsetMode = PixelOffsetMode.HighQuality
    50. .DrawImage(B, New PointF(0, 0))
    51. End With
    52. End Using
    53. End Sub


    Nur Paint (e.graphics)
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Protected Overrides Sub OnPaint(e As PaintEventArgs)
    2. With e.Graphics
    3. .TextRenderingHint = TextRenderingHint.ClearTypeGridFit
    4. .SmoothingMode = SmoothingMode.AntiAlias
    5. .InterpolationMode = InterpolationMode.HighQualityBicubic
    6. .CompositingQuality = CompositingQuality.HighQuality
    7. .PixelOffsetMode = PixelOffsetMode.HighQuality
    8. Dim tmp_Color As Color = Color.DarkGray
    9. Select Case MouseState
    10. Case Helpers.MouseState.None
    11. tmp_Color = _BackGroundColor
    12. Case Helpers.MouseState.Over
    13. tmp_Color = _HoverColor
    14. Case Helpers.MouseState.Pressed
    15. tmp_Color = _ClickColor
    16. End Select
    17. Using BackgroundBrush As New SolidBrush(tmp_Color)
    18. .FillRectangle(BackgroundBrush, New Rectangle(0, 0, Me.Width, Me.Height))
    19. End Using
    20. If _Hatch Then
    21. Using HatchBrush As New HatchBrush(HatchStyle.DarkDownwardDiagonal, Color.FromArgb(75, _HatchColor), Color.Transparent)
    22. .FillRectangle(HatchBrush, New Rectangle(0, 0, Me.Width, Me.Height))
    23. End Using
    24. End If
    25. If _GlassEffect Then
    26. Using GlassEffectBrush As New LinearGradientBrush(New Rectangle(0, 0, Me.Width, Me.Height \ 2), Color.FromArgb(180, _GlassEffectColor), Color.FromArgb(25, _GlassEffectColor), LinearGradientMode.Vertical)
    27. .FillRectangle(GlassEffectBrush, New Rectangle(0, 0, Me.Width, Me.Height \ 2))
    28. End Using
    29. End If
    30. If _Border Then
    31. Using BorderBrush As New SolidBrush(_BorderColor)
    32. Using BorderPen As New Pen(BorderBrush, 2)
    33. .DrawRectangle(BorderPen, New Rectangle(0, 0, Me.Width, Me.Height))
    34. End Using
    35. End Using
    36. End If
    37. Using ButtonTextBrush As New SolidBrush(_TextColor)
    38. .DrawString(ButtonText, Font, ButtonTextBrush, GetTextPosition(.MeasureString(ButtonText, Font)), StringFormat.GenericDefault)
    39. End Using
    40. End With
    41. End Sub



    Welche Methodik wäre die sinnvollere und weswegen ?
    Mein erster Gedanke wäre das evtl. Ram-Vorteile bestehen könnten, aber zumindest lt. Visual Studio 2017 ist bei keiner der Methoden ein Verbrauchsunterschied erkennbar.

    LG
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If

    asusdk schrieb:

    Kompletter Code des Buttons wie ich Ihn Aktuell verwende
    ist das m.E. nicht, denn z.B. in Zeile#149 heißt es Overrides. Das geht aber nur, wenn es eine Basisklasse gibt. Da das CE angeblich aber von nichts erbt, ist der Code entweder unvollständig, nicht funktionsfähig oder Du siehst was, was ich nicht sehe.
    Zum Thema selbst: Da wären wohl Performancetests sinnvoll(er). Aber hey: Warum ein Graphics-Objekt erstellen, wenn e es Dir schon liefert?
    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 nein das ist ein Benutzersteuerelement welches nur diesen Code enthält, mir ist nur diese methode bekannt, daher verwende ich das mit dem Overrides. Welche Möglichkeiten für einen auswertbaren Performancetest wären denn existent / angebracht ?
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    Aah! Benutzersteuerelement. Die Info hat gefehlt.
    Hab mal einen Anfangstest gemacht - keine Ahnung, wie gut der ist, um das zu testen. 10000-100000x die Buttons (einer mit Graphics.FromImage, einer mit e.Graphics) invalidiert und Zeit gemessen. Keine relevanten Unterschiede.
    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.
    Ok, das ist tatsächlich eine gute idee, die tatsächlich benötigte Zeit messen, simple und doch genial, also ist es wohl schlicht eine Frage des Geschmacks bezogen auf die schreibwiese die den Unterschied macht, wär hätts gedacht ^^
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    mir scheint das ineffizient.
    ERst erzeugst du eine Bitmap, dann holst du von der Bitmap das Graphics, damit malste viel herum, und dann malste die ganze Bitmap nochmal ins e.Graphics hinein.
    Warum nicht gleich mittm e.Graphics malen? sparste dir das Erzeugen einer Bitmap und holen ihrer Graphics, und das "Abmalen" der eigenen Bitmap ins e.Graphics.

    (Hat wahrscheinlich keine praktische Relevanz, also ich erwarte keine signifikanten Performance-Unterschiede)
    @ErfinderDesRades Ja so dachte ich mir das auch, hatte diese Methodik in einem CostumTabControl so gesehen, und war mir eben unsicher ob es nicht aus irgendweclhen Gründen relevant ist, daher wollte ich das hiermit klären =)
    If Energy = Low Then
    Drink(aHugeCoffee)
    Else
    Drink(aHugeCoffeeToo)
    End If
    naja - was man irgendwo sieht...
    Ich würde übrigens kein UserControl nehmen, wenn ich einen Button haben will.
    Sondern dann nähme ich einen Button.
    Man kann ja von Button erben, dann muss man nicht alle Button-Features neu programmieren, sondern nur noch diejenigen, die man wirklich hinzufügen will.
    ABer nix gesagt. Controls entwickeln führt einen immer wieder aufs Glatteis - wenn du da jetzt Arbeit von 2 Wochen wegschmeisst, und auf meinen Rat neu anfängst, unds klappt nicht, will ich nicht dran schuld sein ;)

    Auch würde ich nicht für jeden Zeichnungsvorgang einen kompletten Satz neuer Brushes erzeugen und wieder disposen.
    Ich würde das benötigte Instrumentarium als KlassenVariablen einrichten, und dann immer wieder-benutzen.
    Disposen dann, wenn der Button disposed wird (in Overrides Dispose(bool))