Angepinnt [Sammelthread] Code-Korrektur

  • VB.NET

Es gibt 123 Antworten in diesem Thema. Der letzte Beitrag () ist von FormFollowsFunction.

    Bin ich so blind? Ich hab extra danach gesucht, als mir das heute Nacht noch aufgefallen war - aber vermutlich war ich da noch zu müde und heute Morgen hab ich mir die erneute Suche geschenkt... :S

    Edit: Wenn das wirklich der Originalcode der Klasse ist, haben wir hier ein kleines Wunder, denn eigentlich kann das so gar nicht funktionieren. listofstreams wird bereits beim Instanzieren der Klasse, danach aber offensichtlich nicht mehr neu erzeugt. Zu dem Zeitpunkt ist aber das XmlDocument, aus dem die Nodelist zusammengestellt werden soll, zwar immerhin schon instanziert, aber definitiv noch leer.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.

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

    TomWi schrieb:

    Brauchst Du dazu den ganzen Projektordner, oder nur die .sln-Datei?
    Mit lauffähiger Solution ist gemeint, dass man per Doppelklick auf die .sln-Datei das Projekt öffnen kann, und anschließend mit F5 starten kann.
    sone Zip erstellst du, indem du VisualStudio schließt, und dann im Windows-Explorer den Pfad "...\SolutionName\Bin" komplett weglöschst, denn darin sind die Executables enthalten.
    Danach mit einem Zipper den Pfad "...\SolutionNam" zippen und anhängen.

    Noch schlankere Zips macht SolutionExplorer, weil das analysiert die .sln-Datei und die Projekt-Dateien, in denen definiert ist, welche Dateien zum Projekt gehören, und zippt nur die.

    Edit: Ah - neuer Versuch - mal gucken
    Jo - fast :(
    Bitte editiere deinen Beitrag, und hau den Bin-Ordner raus, denn da sind Executables drin.
    Diese Forum-Regel ist nicht Schikane, sondern eine von unbekannter Quelle heruntergeladene Exe ist ein massives Sicherheitsrisiko. Wenn man das frei zuließe, wäre es ein Kinderspiel, die wüstesten Malware-Produkte unters Volk zu bringen - bis hin zu 0190-Dialern und Scherze (naja, bei 0190-Dialern glaubich übrigens, dass dem inzwischen technische Riegel vorgeschoben sind - wissen tu ichs nicht).

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

    Wenn ich deinen Code "verbessern" dürfte, würde er bei mir übrigens so aussehen:

    VB.NET-Quellcode

    1. Public Class frmExpandCollapseLineups
    2. Const STARTPATH As String = "Mein Pfad"
    3. Private Enum ActionType
    4. Expand
    5. Collapse
    6. End Enum
    7. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    8. Using ofd As New OpenFileDialog()
    9. With ofd
    10. .Title = "Choose A3D File"
    11. .Filter = "A3S Files (*.a3s)|*.a3s"
    12. .InitialDirectory = STARTPATH
    13. .FileName = "A3S-Files"
    14. If .ShowDialog() = DialogResult.OK Then
    15. Backup(.FileName)
    16. If RadioButton2.Checked Then
    17. ChangeXml(.FileName, ActionType.Expand)
    18. ElseIf RadioButton1.Checked Then
    19. ChangeXml(.FileName, ActionType.Collapse)
    20. End If
    21. End If
    22. End With
    23. End Using
    24. End Sub
    25. Private Sub ChangeXml(ByVal filename As String, ByVal action As ActionType)
    26. Dim a3sXml As New Xml.XmlDocument
    27. a3sXml.Load(filename)
    28. For Each node As XmlNode In a3sXml.SelectNodes("//alternative_set")
    29. Select Case action
    30. Case ActionType.Collapse
    31. node.Attributes.RemoveNamedItem("open")
    32. Case ActionType.Expand
    33. Dim xmlAttrib = a3sXml.CreateAttribute("open")
    34. xmlAttrib.Value = "1"
    35. node.Attributes.Append(xmlAttrib)
    36. End Select
    37. Next
    38. a3sXml.Save(filename)
    39. Application.Exit()
    40. End Sub
    41. Sub Backup(ByVal filename As String)
    42. Dim backupDir = New DirectoryInfo(Path.Combine(Path.GetDirectoryName(filename), "Backup"))
    43. backupDir.Create()
    44. Dim newFilename As String = Path.Combine(backupDir.FullName, Path.GetFileName(filename))
    45. If File.Exists(newFilename) Then
    46. Dim fileNumber As Integer = 0
    47. Dim fileBase = Path.GetFileNameWithoutExtension(filename)
    48. Dim fileExt = Path.GetExtension(filename)
    49. Do
    50. fileNumber += 1
    51. newFilename = Path.Combine(backupDir.FullName, String.Format("{0} ({1}){2}", fileBase, fileNumber, fileExt))
    52. Loop Until Not File.Exists(newFilename)
    53. End If
    54. File.Copy(filename, newFilename)
    55. End Sub
    56. End Class
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.
    Arby hat geschrieben, dass ich den Starpath so anlegen soll

    VB.NET-Quellcode

    1. Const startpath As String = "Mein Pfad"
    und nicht so wie ich es gemacht habe

    VB.NET-Quellcode

    1. Dim startpath As String = "Mein Pfad"


    kann mir bitte jemand den Unterschied erklären?
    Macht doch eigentlich keinen Unterschied. Const ist eben eine Konstante, die immer gleich bleibt und Dim macht eine Variable draus, die aber durch die Angabe eines fixen Pfades, doch auch immer gleich bleibt.

    Seh ich das richtig?

    Tom
    @Arby:: Na, sowas nenne ich doch einen schnuckligen Code :thumbsup: :thumbsup: .
    Den guckt man an, und kann ihn durchlesen, und sieht, wies geht, und dass die Methoden genau das tun, wie sie heißen (ausser Button1_Click, aber bei nur einem Button auffm Form kann man das verschmerzen).
    Und jede Methode für sich ist eine autarke Einheit, die alle Info über ihre Parameter bekommt, sodass man bei Fehlverhalten kaum jemals mehr als 10 Zeilen zu untersuchen hat, und pipapo. :thumbsup:

    Die beiden üflüssigen Leerzeilen in Button1_Click() täte ich noch fort, und v.a. bei Backup() sollte der Scope Private gesetzt sein - vb macht Methoden ohne Scope-Angabe idiotischerweise Public.

    Ach - und schließen täte ich ein Form immer nur mit Me.Close - Application.Exit() hat in meinen Augen son bischen was von Programm abschießen im Task-Manager.

    Und Hilfreichigkeit ist unwiderleglich, denn @TomWi: sagt ja selber, dasserdas gut lesen kann :)

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

    sonne75 schrieb:

    Anscheinend aktualisiert sich die List von alleine, nachdem das Dokument geladen wurde. 8o
    Am Anfang ist .Count noch 0 und nach dem LoadFile sind da plötzlich 10 Elemente drin.

    Zauberei. Das widerspricht allem, was ich von diesen Klassen erwarten würde. Naja, hoffentlich erinner ich mich bei Gelegenheit wieder daran, wenn ich selbst mal SelectNodes (falsch ge-)brauche, damit ich nicht ewig nach der Ursache eines möglicherweise fehlerhaften Ergebnisses aufgrund dieses Verhaltens suche.

    TomWi schrieb:

    kann mir bitte jemand den Unterschied erklären?

    Vom Ergebnis her gibt es keinen Unterschied, aber wenn du den Inhalt eh nicht änderst, er also konstant bleibt, ist es deshalb besser, die Variable als Konstante zu deklarieren, weil es besser wartbar ist. Unter "wartbar" verstehe ich z.B. die Möglichkeit, auf einen Blick zu sehen: Das Ding kann sich zur Laufzeit nicht ändern - ich muss also nicht erst den Code daraufhin absuchen, falls irgendwo ein Fehler passiert, und kann mich direkt auf andere Fehlerquellen konzentrieren, falls z.B. mal ein Dateiname oder Pfad falsch zusammengebaut werden sollte. Sowas gilt insbesondere in Projekten, die nicht von einer Person bearbeitet werden, sondern wo auch andere den Code verstehen müssen, aber auch für die Fälle, wo man ein Projekt nach mehreren Monaten oder Jahren wieder anfassen und sich wieder in die damals verzapfte Logik reindenken muss.
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.

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

    Arby schrieb:

    Das widerspricht allem, was ich von diesen Klassen erwarten würde.

    Ich denke, es liegt daran, dass die List auf .SelectNodes gelegt wurde, welches seinerseits eine List ist. Und wenn diese List aktualisiert wird (weil .LoadFile gemacht wurde), dann wird auch die erste List mitaktualisiert. Es sind ja sozusagen nur jeweils "Zeiger", also Referenzen, auf die Daten.
    Die erste List ist ein Zeiger auf die zweite List, die zuerst noch auf Nothing zeigt. Dann kommen an die Stelle von Nothing Daten, die zweite List zeigt also auf Daten und die erste List, die auf die zweite zeigt, zeigt auch auf die Daten.

    Hat jemand verstanden, was ich meine? :P

    Übersichtlich ist so ein Code aber überhaupt nicht...

    EDIT: von der anderen Seite, ist .SelectNodes eine Funktion, die eine Liste mit Übereinstimmungen gibt. Wenn es keine gab (weil das Dokument noch Nothing war), wieso werden dann plötzlich Übereinstimmungen gefunden? :?: Na ja, hängt ja vom Code hinter dieser Funktion ab, wenn es nur Referenzen sind, die sich dann erneuern (weil die Daten sich erneuern), dann aktualisieren sich wohl die Daten.
    Wobei es im Objektkatalog steht:
    Rückgabewerte:
    Eine System.Xml.XmlNodeList mit einer Auflistung der Knoten, die mit der XPath-Abfrage übereinstimmen.Das Herstellen einer "Liveverbindung" von XmlNodeList mit dem XML-Dokument sollte nicht erwartet werden.Das heißt, Änderungen, die im XML-Dokument sichtbar sind, werden nicht in der XmlNodeList angezeigt (und umgekehrt).

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

    Für alle Knobler: schlage vor, folgendes Problem zu lösen:
    Bezug: [VB 2010] Item in 2. Combobox löschen, wenn es in der 1. Combox ausgewählt wurde

    Problem schrieb:

    per Combos sollen 6 Eingänge zugewiesen werden. Ist ein Eingang zugewiesen, so soll er in den anneren Combos nicht mehr zur Auswahl stehen. Um damit nicht festzufahren gibt es ein zusätzliches Combo-Item "<keine>", welches immer in allen Combos verfügbar bleibt.

    also gibts 6 Combos, und 7 Items, welche dahinein zu verteilen sind. Und zwar hat jede Combo eine eigene DataSource, und die ist jedesmal, wenn bei irgendeiner der Combos das SelectedIndexChanged auftritt, neu zu berechnen.
    Also am einfachsten leitest du alle SelectedIndexChanged-Events auf eine Methode, und da wird zentral alles neu verteilt.
    Bei der Berechnung brauchst du ein kleines Datenmodell, was du manipulieren kannst, ohne das gleich alle Combos rumhüpfen - das einfachste, mit dem das möglich ist, wäre ein Array von 6 List(Of String) - Objekten.



    Edit: Also hier meine Lösung:

    VB.NET-Quellcode

    1. Public Class frmDependendCombos
    2. Private _SourceSource As String() = "<Kein> Inp1 Inp2 Inp3 Inp4 Inp5 Inp6".Split
    3. Private _Sources(_SourceSource.Length - 2) As List(Of String)
    4. Private _Combos As ComboBox()
    5. Private _Handler As EventHandler = Sub(s, e) AssignSources()
    6. Public Sub New()
    7. InitializeComponent()
    8. _Combos = {ComboBox1, ComboBox2, ComboBox3, ComboBox4, ComboBox5, ComboBox6}
    9. For i = 0 To _Combos.Length - 1
    10. _Sources(i) = New List(Of String)(_SourceSource)
    11. _Combos(i).DataSource = _Sources(i)
    12. Next
    13. EnableEvent(True)
    14. End Sub
    15. Private Sub AssignSources()
    16. EnableEvent(False)
    17. For i = 0 To _Combos.Length - 1
    18. With _Sources(i)
    19. Dim selected = .Item(_Combos(i).SelectedIndex)
    20. .Clear()
    21. .AddRange(_SourceSource)
    22. .Add(selected)
    23. End With
    24. Next
    25. For Each src0 In _Sources
    26. For Each src In _Sources
    27. If src Is src0 Then Continue For
    28. Dim selected = src.Last
    29. If selected <> _SourceSource(0) Then src0.Remove(selected)
    30. Next
    31. Next
    32. For i = 0 To _Combos.Length - 1
    33. Dim src = _Sources(i)
    34. Dim selected = src.Last
    35. src.RemoveAt(src.Count - 1)
    36. _Combos(i).DataSource = Nothing
    37. _Combos(i).DataSource = src
    38. _Combos(i).SelectedIndex = src.IndexOf(selected)
    39. Next
    40. EnableEvent(True)
    41. End Sub
    42. Private Sub EnableEvent(value As Boolean)
    43. If value Then
    44. For Each cmb In _Combos
    45. AddHandler cmb.SelectedIndexChanged, _Handler
    46. Next
    47. Else
    48. For Each cmb In _Combos
    49. RemoveHandler cmb.SelectedIndexChanged, _Handler
    50. Next
    51. End If
    52. End Sub
    53. End Class

    DependendCombos.zip

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

    Hallo alle zusammen,
    auch ich möchte mal meinen Code posten, weil ich noch nicht so wirklich weiß, ob er sauber geschrieben ist.
    Verbesserungsvorschläge aufjedenfall erwünscht :)

    Mein Programm soll eine BinärUhr sein oder besser gesagt, ein Control, was man sich auf jede Anwendung ziehen kann.

    VB.NET-Quellcode

    1. Option Strict On
    2. Option Explicit On
    3. Imports System.Drawing
    4. Imports System.Windows.Forms
    5. Imports System.Drawing.Drawing2D
    6. Public Class BinaryClock
    7. Inherits Panel
    8. Public Sub New()
    9. MyBase.New()
    10. MyBase.SetStyle(ControlStyles.UserPaint, True)
    11. MyBase.SetStyle(ControlStyles.CacheText, True)
    12. MyBase.SetStyle(ControlStyles.DoubleBuffer, True)
    13. MyBase.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    14. MyBase.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    15. MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
    16. With Me
    17. .Name = "BinaryClock"
    18. .Size = New Size(159, 84)
    19. .MinimumSize = New Size(.Width, .Height)
    20. End With
    21. End Sub
    22. Dim styl As New Style
    23. Dim func As New Functions
    24. Dim pblist As New List(Of PictureBox)
    25. Dim binlist As New List(Of String)
    26. Public WithEvents T_BinaryClock As New Timers.Timer
    27. Private Sub BinaryClock_Load(ByVal sender As Object, _
    28. ByVal e As System.EventArgs) Handles Me.HandleCreated
    29. For i As Integer = 0 To 2 Step 1
    30. For j As Integer = 0 To 5 Step 1
    31. Dim pb As New PictureBox
    32. With pb
    33. .Name = i.ToString & "_" & j.ToString
    34. .Size = New Size(24, 24)
    35. .Location = New Point(5 + ((j * 24) + (j * 1)), 5 + ((i * 24) + (i * 1)))
    36. .BackgroundImageLayout = ImageLayout.Center
    37. .BackgroundImage = My.Resources._false
    38. .BackColor = Color.Transparent
    39. End With
    40. pblist.Add(pb)
    41. Next
    42. Next
    43. For Each PB In pblist
    44. Me.Controls.Add(PB)
    45. Next
    46. T_BinaryClock.Interval = 1000
    47. T_BinaryClock.Start()
    48. End Sub
    49. Private Sub BinaryClock_Paint(ByVal sender As Object, _
    50. ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    51. Dim ColorTop As Color = Color.LightGray
    52. Dim ColorBottom As Color = Color.DimGray
    53. Dim r As Rectangle
    54. With MyBase.ClientRectangle
    55. r = New Rectangle(0, 0, .Width - 1, .Height - 1)
    56. End With
    57. Dim radius As Single = 3
    58. styl.DrawFillRoundedRectangle(e.Graphics, r, radius, Color.Black, _
    59. New LinearGradientBrush(r, ColorTop, ColorBottom, _
    60. LinearGradientMode.Vertical))
    61. End Sub
    62. Private Sub BinaryClock_Resize(ByVal sender As Object, _
    63. ByVal e As System.EventArgs) Handles Me.Resize
    64. Invalidate()
    65. End Sub
    66. Private Sub Timer_BinaryClock_Elapsed(ByVal sender As Object, _
    67. ByVal e As EventArgs) Handles T_BinaryClock.Elapsed
    68. With Me
    69. .Name = "BinaryClock"
    70. .Size = New Size(159, 84)
    71. .MinimumSize = New Size(.Width, .Height)
    72. .MaximumSize = New Size(.Width, .Height)
    73. End With
    74. binlist = func.BinarClock(Now.Hour, Now.Minute, Now.Second)
    75. For i As Integer = 0 To binlist.Count - 1
    76. If binlist(i) = "1" Then
    77. pblist(i).BackgroundImage = My.Resources._true
    78. Else
    79. pblist(i).BackgroundImage = My.Resources._false
    80. End If
    81. Next
    82. End Sub
    83. End Class
    84. Public Class Style
    85. Public Sub DrawFillRoundedRectangle(ByVal g As Graphics, _
    86. ByVal r As Rectangle, _
    87. ByVal radius As Single, _
    88. ByVal borderColor As Color, _
    89. ByVal fillBrush As Brush)
    90. Dim path As GraphicsPath = FillRoundedRectanglePath(r, radius)
    91. g.FillPath(fillBrush, path)
    92. g.DrawPath(New Pen(borderColor), path)
    93. path.Dispose()
    94. End Sub
    95. Private Function FillRoundedRectanglePath(ByVal r As RectangleF, _
    96. ByVal radius As Single) As GraphicsPath
    97. Dim path As New GraphicsPath
    98. Dim d As Single = 2 * radius
    99. With path
    100. If radius < 1 Then
    101. .AddRectangle(r)
    102. Else
    103. .AddLine(r.X + radius, r.Y, r.X + r.Width - d, r.Y)
    104. .AddArc(r.X + r.Width - d, r.Y, d, d, 270, 90)
    105. .AddLine(r.X + r.Width, r.Y + radius, r.X + r.Width, r.Y + r.Height - d)
    106. .AddArc(r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90)
    107. .AddLine(r.X + r.Width - d, r.Y + r.Height, r.X + radius, r.Y + r.Height)
    108. .AddArc(r.X, r.Y + r.Height - d, d, d, 90, 90)
    109. .AddLine(r.X, r.Y + r.Height - d, r.X, r.Y + radius)
    110. .AddArc(r.X, r.Y, d, d, 180, 90)
    111. End If
    112. .CloseFigure()
    113. End With
    114. Return (path)
    115. End Function
    116. End Class
    117. Public Class Functions
    118. Public Function BinarClock(ByVal hh As Integer, ByVal mm As Integer, _
    119. ByVal ss As Integer) As List(Of String)
    120. Dim binstring As New List(Of String)
    121. If hh < 12 And hh > 0 Then
    122. binstring.Add("1")
    123. Else
    124. binstring.Add("0")
    125. End If
    126. For i As Integer = 0 To 2 Step 1
    127. Dim temp As String = ""
    128. Select Case i
    129. Case 0
    130. temp = Convert.ToString(hh, 2)
    131. For j As Integer = (4 - temp.Length) To 0 Step -1
    132. binstring.Add("0")
    133. Next
    134. For m As Integer = 0 To temp.Length - 1 Step 1
    135. binstring.Add(temp.Substring(m, 1))
    136. Next
    137. Case 1
    138. temp = Convert.ToString(mm, 2)
    139. For k As Integer = (5 - temp.Length) To 0 Step -1
    140. binstring.Add("0")
    141. Next
    142. For n As Integer = 0 To temp.Length - 1 Step 1
    143. binstring.Add(temp.Substring(n, 1))
    144. Next
    145. Case 2
    146. temp = Convert.ToString(ss, 2)
    147. For l As Integer = (5 - temp.Length) To 0 Step -1
    148. binstring.Add("0")
    149. Next
    150. For o As Integer = 0 To temp.Length - 1 Step 1
    151. binstring.Add(temp.Substring(o, 1))
    152. Next
    153. End Select
    154. Next
    155. Return binstring
    156. End Function
    157. End Class
    Keep Calm And Color Your Life
    Habe nur kurz drüber geschaut und was mir aufgefallen ist:

    VB.NET-Quellcode

    1. MyBase.SetStyle(ControlStyles.UserPaint, True)
    2. MyBase.SetStyle(ControlStyles.CacheText, True)
    3. MyBase.SetStyle(ControlStyles.DoubleBuffer, True)
    4. MyBase.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    5. MyBase.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    6. MyBase.SetStyle(ControlStyles.SupportsTransparentBackColor, True)


    sollte zu dem werden:

    VB.NET-Quellcode

    1. SetStyle(ControlStyles.CacheText Or ControlsStyles.DoubleBuffer Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.SupportsTransparentBackColor, True)
    2. UpdateStyles()
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Und mit den ganzen PictureBoxen sieht das auch etwas komisch aus - wofür brauchst du denn die? In den meisten Fällen sollte GDI+ (besser) funktionieren, und das mit nur einem Control.

    VB.NET-Quellcode

    1. SetStyle(ControlStyles.CacheText Or ControlsStyles.DoubleBuffer Or ControlStyles.AllPaintingInWmPaint Or ControlStyles.OptimizedDoubleBuffer Or ControlStyles.SupportsTransparentBackColor, True)
    2. UpdateStyles()


    Ok, des kannte ich noch garnicht, aber ist ja schön zu wissen, dass man es auch so zusammenfassen kann ;)
    ich habe des alles nur so ausgeschrieben, damit es für mich übersichtlicher aussieht.

    Ja die Pictureboxen sind für mich die Anzeigeboxen für die Uhrzeit und ich dachte es wäre besser einfach deren
    BackgroundImage zu ändern, als immer wieder das Control neu zu Zeichnen.

    Hier mal ein Bild vom Control.
    Um Jeden Punkt ist halt ne PictureBox.
    Bilder
    • BinaryClock.png

      1,4 kB, 171×95, 3.100 mal angesehen
    Keep Calm And Color Your Life

    Cypress schrieb:

    Ja die Pictureboxen sind für mich die Anzeigeboxen für die Uhrzeit und ich dachte es wäre besser einfach deren
    BackgroundImage zu ändern, als immer wieder das Control neu zu Zeichnen.


    Die Picturebox macht ja auch nichts anderes als das Image neu zuzeichnen. Nur steckt hinter der Picturebox noch mehr als nur ein Rendervorgang, weshalb du nur Performance einbüßt.