GDI+ mit Matrix ein Graphicpath Transformieren - Genauigkeit

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

Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    GDI+ mit Matrix ein Graphicpath Transformieren - Genauigkeit

    Guten Abend :) ,

    ich habe wieder eine Frage an euch.
    Ich mache gerade ein kleines Projekt und möchte etwas Zeichnen und Verschieben (+Skalieren).
    Jedoch habe ich einen (Genauigkeits-) Fehler gefunden und möchte fragen ob es hier eine Lösung gibt.

    Hier mal ein kurzer Ausschnitt was ich mache:

    Quellcode

    1. Dim draw As New List(Of GraphicsPath)
    2. Dim ZoomMatrix As New Matrix
    3. Dim myPath1 As New Drawing2D.GraphicsPath()
    4. myPath1.StartFigure()
    5. 'myPath1.AddLine(X1,Y1,X2,Y2)
    6. myPath1.AddLine(398.2465, 100.3343, 633.5666, 100.3343)
    7. draw.Add(myPath1)
    8. ZoomMatrix.Translate(23.565656565, 100, MatrixOrder.Append)
    9. ' Jedes Shape in der Liste wird mit der Zoommatrix transformiert
    10. For Each shape As Drawing2D.GraphicsPath In draw
    11. shape.Transform(ZoomMatrix)
    12. Next

    Wenn ich jetzt in der Liste "draw" reinschaue, dann wird beim "X1" statt "421,81215656" wird "421,812134" berechnet.
    Wie man sieht, ist die Berechnung beim Transformieren (also das Translate) ja sehr ungenau.
    Desweiteren wenn ich jetzt alles rückgängig mache, kommt folgendes:

    Quellcode

    1. ZoomMatrix.Reset()
    2. ZoomMatrix.Translate(-23.565656565, -100, MatrixOrder.Append)
    3. For Each shape As Drawing2D.GraphicsPath In draw
    4. shape.Transform(ZoomMatrix)
    5. Next


    In draw steht beim "X1" statt "398,2465" - "398,24646"
    Wenn ich also mehrmals ins Plus verschiebe und dann wieder alles zurück, wird es noch ungenauer.. ;(


    Ist das bei GDI+ normal ? Gibt es eine Abhilfe ?

    Würde mich auf ein paar Inputs freuen ;)

    Danke :) Gruß

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

    Das ist nicht nur bei GDI+ normal, sondern auch bei sonstigen Zeichenschnittstellen, schließlich geht es beim Rendern um geschwindigkeit nicht um genauigkeit, die idR sowieso nicht Sichtbar ist. DX und OPL bieten natürlich die Möglichkeit double zu verwenden.
    Wenn du tatsächlich fürs zeichnen mehr Genauigkeit brauchen solltest, dann berechne es selbst. Aber ich glaube eher, dass du einen anderen Ansatz verfolgen solltest?
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @Jaask0 Wenn Du einen Single-Parameter mit Double-Werten bestückst, werden die intern gnadenlos abgeschnitten:

    Die Abweichung Deiner Werte liegt in der 8. Stelle, d.h. 7 Stellen stimmen.
    Das ist exakt die Genauigkeit, die Float / Single liefert.
    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!
    DirectX hatte ich mal im Visier, jedoch viel zu kompliziert.
    Natürlich kann man dort weitaus mehr als nur ein paar Linien und Kreise Zeichnen :D

    Dennoch habe ich eine Frage an euch:
    Wenn ich die Graphicpaths skaliere und verschiebe, möchte ich die Paths wieder in den "Ausgangszustand" zurück verschieben.

    Ich habe zwei Ansetze verfolgt:
    1.)

    Quellcode

    1. Dim draw As New List(Of GraphicsPath)
    2. Dim _PanSavex As New List(Of Single) 'Liste für die Verschiebung in X
    3. Dim _PanSavey As New List(Of Single) 'Liste für die Verschiebung in Y
    4. Dim drawScaleSave As New List(Of Single) 'Liste für die Skalierung
    5. Dim ZoomMatrix As New Matrix
    6. [u]Funktion wird aufgerufen[/u]
    7. Dim myPath1 As New Drawing2D.GraphicsPath()
    8. myPath1.StartFigure()
    9. 'myPath1.AddLine(X1,Y1,X2,Y2)
    10. myPath1.AddLine(398.2465, 100.3343, 633.5666, 100.3343)
    11. draw.Add(myPath1)
    12. [u]'Ab hier Mousemove event[/u]
    13. Dim drawScale as Single = 1
    14. drawScale += 0,1 '// Oder drawScale -=0,1
    15. ZoomMatrix.Scale(drawScale, drawScale, MatrixOrder.Append)
    16. ZoomMatrix.Translate(23.5656, 100, MatrixOrder.Append)
    17. drawScaleSave.Add(CSng(1 / (1 + _Step))) 'Speichere den Scale in ArrayList
    18. _PanSavex.Add(23.5656) 'Speichere den PanX in ArrayList
    19. _PanSavey.Add(100) 'Speichere den PanY in ArrayList
    20. ' Jedes Shape in der Liste wird mit der Zoommatrix transformiert
    21. For Each shape As Drawing2D.GraphicsPath In draw
    22. shape.Transform(ZoomMatrix)
    23. Next
    24. Me.Invalidate()
    25. ZoomMatrix.Reset
    26. [u]Button event[/u]
    27. For i = 0 To drawScaleSave.Count - 1
    28. ZoomMatrix.Scale(drawScaleSave(drawScaleSave.Count - 1 - i), drawScaleSave(drawScaleSave.Count - 1 - i), MatrixOrder.Append)
    29. ZoomMatrix.Translate(-_PanSavex(drawScaleSave.Count - 1 - i) * drawScaleSave(drawScaleSave.Count - 1 - i), -_PanSavey(drawScaleSave.Count - 1 - i) * drawScaleSave(drawScaleSave.Count - 1 - i), MatrixOrder.Append)
    30. Next
    31. For Each shape As Drawing2D.GraphicsPath In draw
    32. shape.Transform(ZoomMatrix)
    33. Next
    34. Me.Invalidate()


    Funktiert nur beim drawScale +=0,1 (also beim Zoomen), wenn jedoch im Mousemove Event drawScale -=0,1 ist, dann bekomme ich den Ausgangszustand nicht mehr.

    Zweiter Ansatz:

    Quellcode

    1. Dim draw As New List(Of GraphicsPath)
    2. Dim Save_draw As New List(Of GraphicsPath)
    3. Dim ZoomMatrix As New Matrix
    4. Dim drawScale as Single = 1
    5. [u]Funktion wird aufgerufen[/u]
    6. Dim myPath1 As New Drawing2D.GraphicsPath()
    7. myPath1.StartFigure()
    8. 'myPath1.AddLine(X1,Y1,X2,Y2)
    9. myPath1.AddLine(398.2465, 100.3343, 633.5666, 100.3343)
    10. draw.Add(myPath1)
    11. Save_draw.Add(myPath1)
    12. [u]'Ab hier Mousemove event[/u]
    13. drawScale += 0,1
    14. ZoomMatrix.Scale(drawScale, drawScale, MatrixOrder.Append)
    15. ZoomMatrix.Translate(23.565656565, 100, MatrixOrder.Append)
    16. ' Jedes Shape in der Liste wird mit der Zoommatrix transformiert
    17. For Each shape As Drawing2D.GraphicsPath In draw
    18. shape.Transform(ZoomMatrix)
    19. Next
    20. Me.Invalidate()
    21. ZoomMatrix.Reset
    22. [u]Button event[/u]
    23. draw.Clear()
    24. draw.AddRange(Save_draw)
    25. Me.Invalidate()

    Das Problem ist hier, dass Save_draw im MouseMove-Event "Transformiert" wird, obwohl ich es nirgends durchführe ?(

    Gibt es Tipps wie ich sowas lösen kann ? :rolleyes:
    @Jaask0 Probiere mal einen in Gleitkomma-Arithmetik exakt darstellbaren Wert, z.B (1/8) ) 0.125.
    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: Vielen vielen vielen Danke :thumbsup: !!!
    Mit "1/8" bzw. dann mit "0,5" funktioniert es einwandfrei :D .

    Zu dem Single: Ja das ist mir auch aufgefallen, dass es abgeschnitten wird.
    Durch mehrmaliges Zoomen und dann zurück transformieren, bekomme ich jedoch sehr starke Abweichungen.
    Deshalb habe ich mir jetzt überlegt, dass ich eine "List of String" erstelle (wo ich die genauen Koordinaten abspeichere)
    und diese als "Clone" von der "GraphicPath-Liste" führe.
    Dann habe ich immer die exakten Werte (& an der gleichen Stelle in der Liste).
    Oder gibt es hier eine bessere Alternative ? :rolleyes:
    Die Frage ist vlt. erstmal was für einen Grund hast du überhaupt, dass du von einer Position genau wieder an die vorherige musst?

    Und wie gesagt selbst implementieren ist immer noch die Möglichkeit.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    @jvbsl: Der Grund für das "Zurückverschieben" ist, dass ich auf einen Button drücken möchte und es wird wieder alles zurück gezoomt und verschoben, damit ich die Gesamtzeichnung sehen kann.

    Und zur Genauigkeit: ich möchte dann mit den Koordinaten eine Rechnung aufstellen.
    Da benötige ich eine hohe Genauigkeit.

    Mal ne Frage an alle:
    Gibt es für eine Windows-Forms-Anwendung ein DirectX (z.B. SharpDX). Oder muss dann das Programm in C programmiert werden.
    Denn ich finde es toll, dass ich jetzt einfach die Buttons, Textboxen, usw. einfach reinziehen kann in die Form.
    Desweiteren finde ich die Syntax von VB einfacher. Jetzt würde ich gerne einen Versuch starten ob VB und DirectX kompatibel ist.
    Also die ganzen Werkzeuge wie Buttons, usw. von der Toolbox verwenden, und dann die Zeichnung auf die Form mit DirectX zeichnen.

    Danke :)
    Leider habe ich noch keine Antwort für "DirectX"von euch bekommen und arbeite weiter mit GDI+.

    Jetzt habe ich wieder ein Problem mit GDI+.
    Ein Ausnahmefehler des Typs "System.OutOfMemoryException" ist in System.Drawing.dll aufgetreten.


    Dieses Problem tritt dann auf, wenn eine Ellipse gezeichnet wird und ich die Zeichnung mit dem Mausrad verkleinere.

    Zu dem Zeitpunkt des Fehleres habe ich folgende Werte in Graphicpath-Pathpoints:
    Spoiler anzeigen
    (0) {X = 371.0577 Y = 251.0497} System.Drawing.PointF
    (1) {X = 371.0577 Y = 251.0497} System.Drawing.PointF
    (2) {X = 371.04776 Y = 251.0497} System.Drawing.PointF
    (3) {X = 371.035461 Y = 251.0497} System.Drawing.PointF
    (4) {X = 371.0232 Y = 251.0497} System.Drawing.PointF
    (5) {X = 371.013245 Y = 251.0497} System.Drawing.PointF
    (6) {X = 371.013245 Y = 251.0497} System.Drawing.PointF
    (7) {X = 371.013245 Y = 251.0497} System.Drawing.PointF
    (8) {X = 371.0232 Y = 251.0497} System.Drawing.PointF
    (9) {X = 371.035461 Y = 251.0497} System.Drawing.PointF
    (10){X = 371.04776 Y = 251.0497} System.Drawing.PointF
    (11){X = 371.0577 Y = 251.0497} System.Drawing.PointF
    (12){X = 371.0577 Y = 251.0497} System.Drawing.PointF

    Ich glaube der Fehler tritt dann auf, wenn die Pathpoints sich nicht unterscheiden.
    Hier gibt es dann einen internen Fehler beim Ellipse erstellen und deshalb bekomme ich einen Speicher-Überlauf im Paint-Event.

    Kann ich diesen Fehler abfangen bzw. umgehen ?

    LG
    nunja, weil es ein weilchen dauern wird, bis du GDI+ sinnvoll für solche Dinge verwenden kannst. DirectX ist schön und gut für Polygone, für alle anderen geometrischen Formen zwar auch geeignet, aber das muss man dann selber implementieren(gibt es mehrere Ansätze).

    Und außerdem stimm ich @Gonger96 vollkommen zu, du merkst dir die Verschiebungen als Historie und wenn du zu nem Punkt zurück schieben willst, dann werden einfach die vorangehenden Transformationen aus der Historie entfernt. So würd ich das auch in DX machen.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Ja mit GDI+ komme ich derzeit aus.
    Beim DirectX habe ich überhaupt keinen Anhaltspunkt wo ich anfangen soll bzw. was ich da verwenden sollte.

    Die Verschiebung habe ich mittels einer ArrayList gemerkert und die Verschiebung zum Ursprung klappt bestens :) .

    Jedoch weiß ich nicht wie ich diesen Fehler Ein Ausnahmefehler des Typs "System.OutOfMemoryException" ist in System.Drawing.dll aufgetreten.
    abfangen bzw. umgehen kann.
    Wenn man eine Ellipse zeichnet und dann "weg-zoomt" also verkleinert, dann passiert das.

    Da würd ich euere Hilfe benötigen.

    Gruß

    Jaask0 schrieb:

    dann passiert das.
    Kannst Du mal ein signifikantes Stück Code posten, das diesen Fehler reproduziert?
    Mach dazu ggf. ein kleines Testprojekt.
    Nebeneffekt: Ggf. findest Du dabei den Fehler selbst.
    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: Vielen dank für deine Mithilfe!
    Hier passiert der Fehler:

    Quellcode

    1. For i As Integer = 0 To draw.Count - 1
    2. e.Graphics.DrawPath(MyPen, draw(i))
    3. Next


    Ein vollständiges WindowsForm-Testprojekt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Imports System.Drawing
    3. Public Class Form1
    4. Public draw As New List(Of GraphicsPath)
    5. Private MyPen As New Pen(Color.Black, 2)
    6. Public ZoomMatrix As New Matrix
    7. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    8. 'Hier wird jetzt eine Ellipse in der draw-Liste hinzugefügt
    9. Dim myPath1 As New Drawing2D.GraphicsPath()
    10. myPath1.StartFigure()
    11. myPath1.AddEllipse(100, 100, 10, 10)
    12. myPath1.CloseFigure()
    13. ' myPath1 in die Liste einfügen
    14. draw.Add(myPath1)
    15. End Sub
    16. Private Sub _MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel
    17. Dim drawScale As Double = 1
    18. drawScale += 1 / 2 '_Step * (-1)
    19. drawScale = 1 / drawScale
    20. ZoomMatrix.Scale(CSng(drawScale), CSng(drawScale), MatrixOrder.Append) 'Skaliere
    21. For Each shape As Drawing2D.GraphicsPath In draw 'Wird auf die Liste angewendet
    22. shape.Transform(ZoomMatrix)
    23. Next
    24. ZoomMatrix.Reset() 'Reset die Matrix
    25. Me.Invalidate() 'Erkläre die Form als ungültig
    26. End Sub
    27. Private Sub Form2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
    28. MyBase.DoubleBuffered = True ' Reduziert Flackern beim Zoomen
    29. e.Graphics.SmoothingMode = SmoothingMode.HighQuality ' Hohe Qualität der Zeichnung ein
    30. For i As Integer = 0 To draw.Count - 1 'Zeichne alle Objekte
    31. e.Graphics.DrawPath(MyPen, draw(i))
    32. Next
    33. End Sub
    34. End Class


    Ich habe nur das Wesentliche aus meinem Programm verwendet.
    Leider habe ich keinen Fehler gefunden ;( .
    Einfach so lang verkleinern, bis "Error" erscheint ;) .

    Vielen Dank!! :)
    @Jaask0 Glückwunsch, Du hast wohl einen Framework-Fehler gefunden. :thumbsup:
    Es hat eine Weile gedauert, bis ich das rausgefunden habe.
    Zunächst habe ich Deinen Code so aufgeräumt, bis nur noch Elementaroperationen übrig blieben und diese nur noch im Paint-Event aufgerufen wurden.
    Die Exception blieb, beim 13. Aufruf knallte es.
    Dann habe ich eine andere Transformation verwendet, Translation statt Skalierung.
    Und siehe, es knallt nicht mehr.
    Dann habe ich noch ein anderes Objekt verwendet, ein Rechteck statt einer Ellipse,
    und siehe, es knallt auch nicht.
    ===
    Fazit: Es knallt bei Skalierung von Ellipsen.
    ===
    Das bedeutet allerdings, dass Dir da im Moment nicht zu helfen ist. ;(
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Imports System.Drawing
    3. Public Class Form1
    4. Public draw As New List(Of GraphicsPath)
    5. Private MyPen As New Pen(Color.Black, 2)
    6. Public ZoomMatrix As Matrix
    7. Private drawScale As Single = 1.0F / 1.5F
    8. Private count As Integer = 0
    9. Private offset As Integer = 1
    10. Public Sub New()
    11. Me.InitializeComponent()
    12. Me.ZoomMatrix = New Matrix
    13. Me.ZoomMatrix.Scale(drawScale, drawScale, MatrixOrder.Append) 'Skaliere
    14. End Sub
    15. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    16. 'Hier wird jetzt eine Ellipse in der me.draw-Liste hinzugefügt
    17. Dim myPath1 As New Drawing2D.GraphicsPath()
    18. myPath1.StartFigure()
    19. ' aktivieren oder nicht
    20. 'myPath1.AddEllipse(100, 100, 10, 10) ' knallt
    21. myPath1.AddRectangle(New Rectangle(50, 50, 20, 20)) ' knallt nicht
    22. myPath1.CloseFigure()
    23. ' myPath1 in die Liste einfügen
    24. Me.draw.Add(myPath1)
    25. MyBase.DoubleBuffered = True ' Reduziert Flackern beim Zoomen
    26. End Sub
    27. Private Sub _MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseWheel
    28. Me.count += 1
    29. If e.Delta > 0 Then
    30. Me.offset += 1
    31. Else
    32. Me.offset -= 1
    33. End If
    34. Me.Label1.Text = Me.count.ToString ' Anzahl der Aufrufe ausgeben
    35. Me.Invalidate() 'Erkläre die Form als ungültig
    36. End Sub
    37. Private Sub Form2_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
    38. e.Graphics.SmoothingMode = SmoothingMode.HighQuality ' Hohe Qualität der Zeichnung ein
    39. ZoomMatrix = New Matrix
    40. If True Then ' hier True oder False reinschreiben
    41. ' knallt
    42. ZoomMatrix.Scale(Me.drawScale, Me.drawScale, MatrixOrder.Append) ' skalieren
    43. Else
    44. ' knallt nicht
    45. ZoomMatrix.Translate(Me.offset, 0) ' verschieben
    46. End If
    47. For i As Integer = 0 To draw.Count - 1 'Zeichne alle Objekte
    48. Me.draw(i).Transform(ZoomMatrix)
    49. e.Graphics.DrawPath(Me.MyPen, Me.draw(i))
    50. Next
    51. End Sub
    52. 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!
    @RodFromGermany vielen Dank für deinen Versuch !! :thumbup:
    Leider habe ich den Fehler gefunden :whistling: .
    Alle Objekte, außer einer Ellipse und einem ARC, können ohne Probleme skaliert werden.
    Transformationen funktionieren aber überall :rolleyes: .

    Schade, dass es keine Lösung gibt. Dann muss ich eine Lösung finden, wo dieser Fehler nicht produziert wird.
    Im Vorfeld die Ellipse bzw. Arc überprüfen ob es bei dieser Skalierung Probleme geben könnte, wenn ja, nicht mehr Skalieren.
    Da wird "was" auf mich zukommen :D .

    @RodFromGermany was verwendest du Grundsätzlich um Objekte zu zeichnen 2D/3D ?
    Gibt es bessere Alternativen ? :/
    Ich benötige derzeit nur 2D, jedoch würde ich vielleicht später auch ein wenig 3D zeichnen.
    Kann man diesen Framework-Fehler an Microsoft reporten?
    Dann können Sie es gleich in der VS 2017 richtig machen :D .

    Liebe Grüße
    @Jaask0 Man könnte den Fehler an Microsoft melden und auf ein Update warten. :/
    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!
    das ist nen Bug der im .Net Framework ist, nicht in VS, hat also nichts mit VS2017 zu tun.

    Alternative wäre WPF, was ich ansich nicht mag, weil es mit so wenig Vorraussicht auf Plattformunabhängigkeit gearbeitet haben.
    Aber winForms ist halt auch uralt so gesehen.
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    Dann werde ich das Problem an MS melden :D .

    @jvbsl: WPF ist auch nichts für mich :rolleyes:.

    Ich habe noch eine kleine Frage an euch und dann sollte alles geklärt sein.

    Wenn ich ein Objekt "hervorheben" möchte (MouseOver), wie soll ich da vorgehen ?

    Derzeit mach ich folgendes:

    VB.NET-Quellcode

    1. 'Im MouseMove-Event:
    2. For Each shape As Drawing2D.GraphicsPath In draw
    3. If shape.IsOutlineVisible(e.X, e.Y, SelectPen2, Gr) = True Then
    4. PointShow = draw.IndexOf(shape) 'Speichere die Position des Items
    5. Exit For
    6. End If
    7. Next
    8. 'Im Paint Event:
    9. If PointShow >= 0 Then
    10. e.Graphics.DrawPath(RedPen2, draw(PointShow))
    11. End If


    Diese Lösung funktioniert, dennoch finde ich es nicht gut, die "draw"-Liste in jedem "Move-Ereignis" durchzugehen.
    Wenn in der Liste 2000 Objekte drinnen sind, dann wird es ein wenig dauern :/ .
    @Jaask0 Invalidisiere nur das, was auch wirklich zu malen ist, also z.B. ein Rechteck um die Mausposition.
    Fang an und male ein Rechteck um das Objekt, im Sinne eines Fokus-Rects oder lass einen randlosen nicht modalen Dialog erscheinen, dessen Opacity 0,5 ist.
    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!