Einstieg in GDI+ (Ausführlich)

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von timmi31061.

    Einstieg in GDI+ (Ausführlich)

    ErfinderDesRades - Moderator - Notiz: Dieses Tutorial ist veraltet. Ein besseres findet sich hier: Tutorial: GDI+
    Und hier noch weiterführendes: [TUTORIAL] Pen & Linien in GDI+



    Ich hab neue Wasserfarben!
    Oh.. Ich male immernoch mit GDI+
    Hey,

    ich habe vor ein paar Wochen angefangen, ein wenig mit GDI+ zu spielen und wollte euch nun auch mal den Einstieg mit diesem kleinen Tutorial vereinfachen =)


    Aufbau

    1. Einfache Linien >>malen<<
    2. Ein Rechteck und weitere geometrische Formen
    3. Abschluss

    Teil 1: Einache Linien >>malen<<

    Man kennt es ja von den Grafikbibliotheken in z.B. C++:
    alles ist aufwendig, schwer zu verstehen und braucht folglich viel Zeit.

    Nicht so in VB.NET mit GDI+!

    Ich werde zuerst mal den ganzen Code posten und ihn dann in Teilen erklären.

    VB.NET-Quellcode

    1. Dim graphic As Graphics
    2. Dim p As Pen
    3. graphic = Me.CreateGraphics()
    4. p = New Pen(System.Drawing.Color.Black, 10)
    5. grahic.DrawLine(p, 0, 0, Me.Width, Me.Height)



    Nun zur Erklärung

    VB.NET-Quellcode

    1. Dim graphic As Graphics
    2. Dim p As Pen

    Sind erstmal Variablen, die wir zum Zeichnen brauchen.
    Das Pen-Objekt sollte sich von selbst erklären, es beinhaltet später die Eigenschaften des >>Stiftes<<, mit dem wir zeichnen.

    Das Graphics-Object stellt u.A. die Funktionen bereit, die wir zum Zeichnen brauchen.

    VB.NET-Quellcode

    1. graphic = Me.CreateGraphics()

    Mit Me.CreateGraphics() stellt sich die Form als >>Papier<< für unsere Zeichnung zur verfügung.

    VB.NET-Quellcode

    1. p = New Pen(System.Drawing.Color.Black, 10)

    Wir >>suchen uns einen Stift aus<< , in unserem Fall soll es ein 10 Pixel (ja, hier wird in Pixeln gerechnet) großer, schwarzer Buntstift sein.


    VB.NET-Quellcode

    1. graphic.DrawLine(p, 0, 0, Me.Width, Me.Height)

    Wir fangen an zu zeichnen. Wir wollen einen Strich von dem Punkt a(0|0) nach b(Me.Width|Me.Height)(z.B. b(100|100)) mit dem vorhin gewählten Stift(p) zeichnen.

    Die Punkte sind in einem gedachten Koordinatensystem(von links oben ausgehend.).

    ACHTUNG: Man kann eine "Malaktion" nicht durch den MyBase.Load-Handler auslösen!!

    Teil 2: Ein Rechteck und weitere geometrische Formen

    VB.NET-Quellcode

    1. Dim graphic As Graphics = Me.CreateGraphics
    2. Dim pen As New Pen(Color.Black, 1)
    3. Dim rec As New Rectangle(1, 1, 100, 100)
    4. graphic.DrawRectangle(pen, rec)


    VB.NET-Quellcode

    1. Dim graphic As Graphics = Me.CreateGraphics
    2. Dim pen As New Pen(Color.Black, 1)

    Gleiches verfahren wie vorher, nur kürzer.

    VB.NET-Quellcode

    1. Dim rec As New Rectangle(1, 1, 100, 100)

    Wir erzeugen ein vorerst nicht sichtbares Rechteck, welches wir später am Punkt p(0|0) mit Höhe 100 Pixel und Breite 100 Pixel zeichnen möchten

    VB.NET-Quellcode

    1. graphic.DrawRectangle(pen, rec)

    Das sollte sich wohl von selbst erklären.
    Ja, die Graphics-Instanz stellt für jede geom.(nicht-dreidimensionale, afaik) Form eine draw-Funktion bereit.

    Unten auf der Seite gibt es eine schöne Tabelle an Funktionen.

    Teil 3: Abschluss

    So, ich habe hier noch eine kleine Funktion für ein Gitter mit 5² Pixeln unterteilung geschrieben ;)

    VB.NET-Quellcode

    1. Dim graphic As Graphics = Me.CreateGraphics
    2. Dim pen As New Pen(Color.Black, 1)
    3. For i As Integer = 0 To Me.Width
    4. graphic.DrawLine(pen, i, 0, i, Me.Height)
    5. i += 4
    6. Next
    7. For i As Integer = 0 To Me.Height
    8. graphic.DrawLine(pen, 0, i, Me.Width, i)
    9. i += 4
    10. Next


    Hoffe ihr konntet was lernen =)



    lg.

    PS: Ich weiß, es ist nichts besonderes für die, die es können, aber für Leute die das nicht können... :)
    ~Edit: Wenn ihr das anseht, dann bitte auch Feedback abgeben..

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

    martinustreveri schrieb:

    ACHTUNG: Man kann eine "Malaktion" nicht durch den MyBase.Load-Handler auslösen!!

    Logisch, wenn die Form noch nicht geladen ist und nichts angezeigt wird, kann man auch nicht drauf zeichnen. Hier schafft entweder das Paint Event oder das Shown Event aushilfe.

    martinustreveri schrieb:

    VB.NET-Quellcode

    1. Dim rec As New Rectangle(1, 1, 100, 100)


    Wir erzeugen ein vorerst nicht sichtbares Rechteck, welches wir später am Punkt p(0|0) mit Höhe 100 Pixel und Breite 100 Pixel zeichnen möchten

    Wenn du das Rechteck am Punkt p(1|1) definierst, wird es aber nicht auf Punkt p(0|0) sondern auch auf p(1|1) gezeichnet ;).

    martinustreveri schrieb:


    VB.NET-Quellcode

    1. Dim graphic As Graphics = Me.CreateGraphics
    2. Dim pen As New Pen(Color.Black, 1)
    3. For i As Integer = 0 To Me.Width
    4. graphic.DrawLine(pen, i, 0, i, Me.Height)
    5. i += 4
    6. Next
    7. For i As Integer = 0 To Me.Height
    8. graphic.DrawLine(pen, 0, i, Me.Width, i)
    9. i += 4
    10. Next

    Hier sollte man für i += 4 in der For Schleife einen Step +4 angeben ;).

    Nochmal um das Tutorial etwas zu erweitern, wie man ein Graphics Object bekommt.
    Es wurde ja schon gesagt wie von der Form (mit Me.CreateGraphics()), aber es ist nat. auch möglich auf Bilder zu zeichnen. Das geht dann mit Graphics.FromImage(bild), wobei bild vom Typ Image sein sollte.

    Dann noch das Paint Event was ganz wichtig ist. Es wird immer ausgelöst wenn die Form erzeugt wird, wenn sie vergrößert wird und auch wenn die Form neugezeichnet wird.
    Dort holt man sich das Graphics Object aus den EventArgs. Also:

    VB.NET-Quellcode

    1. Dim g As Graphics = e.Graphics

    Man kann das Paint Event auch selbst auslösen, so:

    VB.NET-Quellcode

    1. con.Invalidate()
    wobei "con" nat. für ein Control oder eine Form steht.
    Man kann auch nur einen bestimmten Bereich neuzeichnen so:

    VB.NET-Quellcode

    1. con.Invalidate(New Region(New Rectangle(x, y, Weite, Höhe))
    Also ich habe das ganze jetzt einfach mal testweise kopiert und in eine Subroutine gesetzt zu der die Variablen übergeben werden, aber es wird nichts gezeichnet.

    Spoiler anzeigen

    Quellcode

    1. Imports Microsoft.DirectX
    2. Imports Microsoft.DirectX.Direct3D
    3. Public Class Form1
    4. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    5. Me.Size = New Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
    6. Fullscreen.Size = New Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
    7. Auflösung.Text = Screen.PrimaryScreen.Bounds.Width & "x" & Screen.PrimaryScreen.Bounds.Height
    8. Select Case Screen.PrimaryScreen.Bounds.Width / Screen.PrimaryScreen.Bounds.Height
    9. Case 16 / 9
    10. Auflösung.Text += " (16:9)"
    11. Case 16 / 10
    12. Auflösung.Text += " (16:10)"
    13. Case 4 / 3
    14. Auflösung.Text += " (4:3)"
    15. End Select
    16. End Sub
    17. Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    18. Const HKEY_LOCAL_MACHINE = &H80000002
    19. Dim objRegistry As Object = GetObject("winmgmts:\\.\root\default:StdRegProv")
    20. Dim strValue As String = ""
    21. Dim strVersion As String = ""
    22. Dim strKeyPath As String = "Software\Microsoft\DirectX"
    23. Dim strValueName As String = "Version"
    24. objRegistry.GetStringValue(HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue)
    25. Select Case strValue
    26. Case "4.02.0095"
    27. strVersion = "1.0"
    28. Case "4.03.00.1096"
    29. strVersion = "2.0a"
    30. Case "4.04.00.0068"
    31. strVersion = "3.0"
    32. Case "4.04.00.0069"
    33. strVersion = "3.0"
    34. Case "4.04.00.0070"
    35. strVersion = "3.0a"
    36. Case "4.05.00.0155"
    37. strVersion = "5.0"
    38. Case "4.05.01.1600"
    39. strVersion = "5.2"
    40. Case "4.05.01.1998"
    41. strVersion = "5.2"
    42. Case "4.06.00.0318"
    43. strVersion = "6.0"
    44. Case "4.06.02.0436"
    45. strVersion = "6.1"
    46. Case "4.06.03.0518"
    47. strVersion = "6.1a"
    48. Case "4.07.00.0700"
    49. strVersion = "7.0"
    50. Case "4.07.00.0716"
    51. strVersion = "7.0a"
    52. Case "4.07.01.3000"
    53. strVersion = "7.1"
    54. Case "4.08.00.0400"
    55. strVersion = "8.0"
    56. Case "4.08.01.0810"
    57. strVersion = "8.1"
    58. Case "4.08.01.0881"
    59. strVersion = "8.1"
    60. Case "4.08.01.0901"
    61. strVersion = "8.1a"
    62. Case "4.08.02.0134"
    63. strVersion = "8.2"
    64. Case "4.09.00.0900"
    65. strVersion = "9.0"
    66. Case "4.09.00.0901"
    67. strVersion = "9.0a"
    68. Case "4.09.00.0902"
    69. strVersion = "9.0b"
    70. Case "4.09.00.0903"
    71. strVersion = "9.0c"
    72. Case "4.09.00.0904"
    73. strVersion = "9.0c"
    74. Case "4.09.0000.0904"
    75. strVersion = "9.28"
    76. Case "6.00.6000.16386"
    77. strVersion = "10"
    78. Case "6.00.6001.18000"
    79. strVersion = "10.1"
    80. Case "6.01.7000.0000"
    81. strVersion = "11"
    82. Case Else
    83. strVersion = "nicht bekannt"
    84. End Select
    85. Auflösung.Text += " DirectX-Version: " & strVersion & " (" & strValue & ")"
    86. Box_zeichnen(20, 20, 100, 100)
    87. End Sub
    88. Private Sub Fullscreen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Fullscreen.Click
    89. Close()
    90. End Sub
    91. Private Sub Box_zeichnen(ByVal bx, ByVal by, ByVal bwidth, ByVal bheight)
    92. Dim graphic As Graphics = Me.CreateGraphics
    93. Dim pen As New Pen(System.Drawing.Color.Black, 1)
    94. Dim rec As New Rectangle(bx, by, bwidth, bheight)
    95. graphic.DrawRectangle(pen, rec)
    96. End Sub
    97. End Class

    du hast grad DX mit GDI vermischt ... es kann sein dass dein DX dein GDI übermalt

    DragonSam schrieb:

    Also ich habe das ganze jetzt einfach mal testweise kopiert und in eine Subroutine gesetzt zu der die Variablen übergeben werden, aber es wird nichts gezeichnet.

    Spoiler anzeigen

    Quellcode

    1. Imports Microsoft.DirectX
    2. Imports Microsoft.DirectX.Direct3D
    3. Public Class Form1
    4. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    5. Me.Size = New Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
    6. Fullscreen.Size = New Size(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height)
    7. Auflösung.Text = Screen.PrimaryScreen.Bounds.Width & "x" & Screen.PrimaryScreen.Bounds.Height
    8. Select Case Screen.PrimaryScreen.Bounds.Width / Screen.PrimaryScreen.Bounds.Height
    9. Case 16 / 9
    10. Auflösung.Text += " (16:9)"
    11. Case 16 / 10
    12. Auflösung.Text += " (16:10)"
    13. Case 4 / 3
    14. Auflösung.Text += " (4:3)"
    15. End Select
    16. End Sub
    17. Private Sub Form1_Shown(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Shown
    18. Const HKEY_LOCAL_MACHINE = &H80000002
    19. Dim objRegistry As Object = GetObject("winmgmts:\\.\root\default:StdRegProv")
    20. Dim strValue As String = ""
    21. Dim strVersion As String = ""
    22. Dim strKeyPath As String = "Software\Microsoft\DirectX"
    23. Dim strValueName As String = "Version"
    24. objRegistry.GetStringValue(HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue)
    25. Select Case strValue
    26. Case "4.02.0095"
    27. strVersion = "1.0"
    28. Case "4.03.00.1096"
    29. strVersion = "2.0a"
    30. Case "4.04.00.0068"
    31. strVersion = "3.0"
    32. Case "4.04.00.0069"
    33. strVersion = "3.0"
    34. Case "4.04.00.0070"
    35. strVersion = "3.0a"
    36. Case "4.05.00.0155"
    37. strVersion = "5.0"
    38. Case "4.05.01.1600"
    39. strVersion = "5.2"
    40. Case "4.05.01.1998"
    41. strVersion = "5.2"
    42. Case "4.06.00.0318"
    43. strVersion = "6.0"
    44. Case "4.06.02.0436"
    45. strVersion = "6.1"
    46. Case "4.06.03.0518"
    47. strVersion = "6.1a"
    48. Case "4.07.00.0700"
    49. strVersion = "7.0"
    50. Case "4.07.00.0716"
    51. strVersion = "7.0a"
    52. Case "4.07.01.3000"
    53. strVersion = "7.1"
    54. Case "4.08.00.0400"
    55. strVersion = "8.0"
    56. Case "4.08.01.0810"
    57. strVersion = "8.1"
    58. Case "4.08.01.0881"
    59. strVersion = "8.1"
    60. Case "4.08.01.0901"
    61. strVersion = "8.1a"
    62. Case "4.08.02.0134"
    63. strVersion = "8.2"
    64. Case "4.09.00.0900"
    65. strVersion = "9.0"
    66. Case "4.09.00.0901"
    67. strVersion = "9.0a"
    68. Case "4.09.00.0902"
    69. strVersion = "9.0b"
    70. Case "4.09.00.0903"
    71. strVersion = "9.0c"
    72. Case "4.09.00.0904"
    73. strVersion = "9.0c"
    74. Case "4.09.0000.0904"
    75. strVersion = "9.28"
    76. Case "6.00.6000.16386"
    77. strVersion = "10"
    78. Case "6.00.6001.18000"
    79. strVersion = "10.1"
    80. Case "6.01.7000.0000"
    81. strVersion = "11"
    82. Case Else
    83. strVersion = "nicht bekannt"
    84. End Select
    85. Auflösung.Text += " DirectX-Version: " & strVersion & " (" & strValue & ")"
    86. Box_zeichnen(20, 20, 100, 100)
    87. End Sub
    88. Private Sub Fullscreen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Fullscreen.Click
    89. Close()
    90. End Sub
    91. Private Sub Box_zeichnen(ByVal bx, ByVal by, ByVal bwidth, ByVal bheight)
    92. Dim graphic As Graphics = Me.CreateGraphics
    93. Dim pen As New Pen(System.Drawing.Color.Black, 1)
    94. Dim rec As New Rectangle(bx, by, bwidth, bheight)
    95. graphic.DrawRectangle(pen, rec)
    96. End Sub
    97. End Class

    Hi,
    probiers mal mit graphics.flush / Me.refresh !

    @Topic
    Ich zeichne immer im Form_Load ohne probleme!
    Mfg
    Loadsoft
    Ich denke er meinte, dass du die Funktion von dem Graphics-Objekt ausführen sollst.
    Ist ja klar, wenn du kein Objekt namens Graphics hast (was ja nicht geht, da die Klasse ja so heißt..) wird auch nichts gehen.

    Man kann übrigens auch ein sehr einfaches PingPong Spiel so schreiben(mit wenig Aufwand), man muss halt immer prüfen ob ob der Ball auf diese Bretterdinger kommt, wenn ja einfach im gespiegelten Winkel weitertitschen lassen, wenn doch einfach normal weiter..^^)

    lg.
    Dieser Thread ist ja alt aber wollte mich mal zu GDI leicht rantasten, da wir gerade Java2D in der berufsschule anschauen und GDI wohl nicht sehr viel anders sein wird ausser vielleicht noch einfacher. Nun siehts bei mir wie folgt aus:

    VB.NET-Quellcode

    1. Public Class Form1
    2. Public Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    3. End Sub
    4. Private Sub TabPage1_Click(sender As System.Object, e As System.EventArgs) Handles TabPage1.Click
    5. Dim graphic As Graphics
    6. Dim p As Pen
    7. graphic = Me.CreateGraphics()
    8. p = New Pen(System.Drawing.Color.Black, 10)
    9. graphic.DrawLine(p, 50, 50, 100, 100)
    10. End Sub
    11. End Class

    Hab mal sowas probiert, aber scheint nicht zu funktionieren kann mir jemand erklären wieso?
    (Auch wenn ich direkt in die Form1_Load schreibe passiert nichts.
    Metal-Schweiz wurde nun offiziell veröffentlich nach all den Jahren :)

    @L.Orion::
    Mach das im Paint-Event deines Controls. Dann kannst du mit e.Graphics auf das GDI-Objekt zugreifen. Außerdem wird das dann bei jedem Renderdurchgang ausgeführt und nicht überschreiben.
    Mit freundlichen Grüßen,
    Thunderbolt