Tastatur Zeichnen (GDI+ oder fuschen?)

  • VB.NET

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

    Tastatur Zeichnen (GDI+ oder fuschen?)

    Hallo,
    ich möchte in meiner Form eine Tastatur zeichnen.
    Ziel ist es, ein Programm zum testen der Tastatur zu schreiben.
    (die Tastatur soll mit der Größe der Form wachsen/schrumpfen)
    Betätige ich eine Taste auf der Tastatur, soll entsprechende Taste im Programm andersfarbig dargestellt werden.
    Beispiel aus einem anderen Programm:






    Ich bin mir aber nicht sicher, wie ich die Tastatur zeichnen soll.
    Anfangs habe ich versucht, das mit TableLayoutPanels zu lösen.
    Hat nur lausige 18 TableLayoutPanels gebraucht, bis ich ein Gebilde hatte, welches als Tastatur zu erkennen war :P
    Es war sogar noch ganz performant, wenn ich die Größe der Form verändert habe.
    Kleines Bildchen bei betätigter Leertaste:






    Aber irgendwie war mir das nicht Professionell genug. Ich wollte es direkt "richtig" machen.
    Also probierte ich jede Taste einzeln zu zeichnen. Natürlich nie in Pixel Angaben, sondern alles Prozentual zur Form Breite & Höhe:






    Funktionierte soweit auch gut. Zumindest solange bis ich mich das erste mal gefragt habe, wie ich die einzelnen gezeichneten Rechtecke farbig bekomme, wenn ich mal eine Taste drücke.
    Ich meine, das sind einfach hintereinander weg gezeichnete Rechtecke. Keine Objekte denen ich mal eben eine neue Farbe verpassen kann.

    Meinen Test Code kann ich auch mal anhängen:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub frmTestsInput_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    2. Dim z As Graphics = CreateGraphics()
    3. Dim pen As New Pen(Color.Black, 1)
    4. Dim BrushText As New SolidBrush(Color.White)
    5. Dim BrushRectangle As New SolidBrush(Color.Black)
    6. Dim font As New Font("Arial", 10)
    7. z.Clear(BackColor)
    8. 'ESC
    9. z.FillRectangle(BrushRectangle, 10, 10, CInt(Me.Width / 100 * 6), CInt(Me.Height / 100 * 10))
    10. z.DrawString("ESC", font, BrushText, 10, 10)
    11. ' F1 - F4
    12. z.FillRectangle(BrushRectangle, CInt(Me.Width / 100 * 10), 10, CInt(Me.Width / 100 * 6), CInt(Me.Height / 100 * 10))
    13. z.DrawString("F1", font, BrushText, CInt(Me.Width / 100 * 10), 10)
    14. z.FillRectangle(BrushRectangle, CInt(Me.Width / 100 * 16.5), 10, CInt(Me.Width / 100 * 6), CInt(Me.Height / 100 * 10))
    15. z.DrawString("F2", font, BrushText, CInt(Me.Width / 100 * 16.5), 10)
    16. z.FillRectangle(BrushRectangle, CInt(Me.Width / 100 * 23), 10, CInt(Me.Width / 100 * 6), CInt(Me.Height / 100 * 10))
    17. z.DrawString("F3", font, BrushText, CInt(Me.Width / 100 * 23), 10)
    18. z.FillRectangle(BrushRectangle, CInt(Me.Width / 100 * 29.5), 10, CInt(Me.Width / 100 * 6), CInt(Me.Height / 100 * 10))
    19. z.DrawString("F4", font, BrushText, CInt(Me.Width / 100 * 29.5), 10)
    20. End Sub




    Gleich mal noch eine Nebenbaustelle:
    Ich habe sowohl in meinem VB.Net Büchlein, als auch hier im Forums Tutorial gelesen, das ich im ​Paint Event ​e.Graphics verwenden soll/muss/kann.
    Das hat aber im Gegensatz zu ​Dim z As Graphics = CreateGraphics() den Nachteil, das sich beim ändern der Formgröße nichts aktualisiert. Habe ich da etwas falsch gemacht?


    Zurück zum Hauptproblem:
    Mir fehlt das nötige Konzept, um mein Vorhaben umsetzen zu können.
    Ich würde mich da über Vorschläge eurerseits freuen.
    Auf der Form zu zeichnen ist etwas langsamer. Benutzt lieber ein Panel oder eine Picturebox. Du kannst auch noch ein paar Styles in der Form oder dem Control setzen:

    VB.NET-Quellcode

    1. SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.UserPaint, true)

    Ein etwas anderer Ansatz

    ... aber vielleicht inspiriert er Dich ja:
    Anstatt die ganze Tastatur zu Zeichen, könntest Du auch ein eigenes Control erstellen, das eine Taste auf der Tastatur repräsentiert.
    Dann könntest Du Dein Control auch später in eine Lib. stecken und gegeben falls später erneut verwenden. :D

    Microsoft hat sogar im MSDN ein Artikel wie man solch ein eigenes Control erstellt: Erstellen von Visual-Basic-.NET-Steuerelementen
    Die Performance ist dieselbe, egal ob auf Form, Picturebox oder Panel gezeichnet wird. Weil sind alles Controls, und ihr PaintEventargs ist dasselbe.
    Aber auf ein Panel ist sinnvoll, damit man evtl. noch annere Sachen aufs Form packen kann.
    Und ja, ich würde auch ein Tastatur-Control erfinden, geerbt von Control.
    Aber zum Zeichnen muss noch 'ne Menge mehr erfunden werden, also da muss man richtig OOP anwenden - Vererbung habich schon genannt, aber auch eine Taste-Klasse als ZeichenObjekt wäre zu schaffen, also eine Einheit, die weiß, wie sie sich selbst als Taste zeichnet.
    Und dann ist vorteilhaft - na eiglich erforderlich, dass man mit Drawing2D.Graphicspath und Drawing2D.Matrix umgehen kann, sonst macht man sich nur schwer.
    @Anluin
    Ja, das hilft sehr. Genau so habe ich es jetzt gemacht.Das Tutorial war auch super.

    ErfinderDesRades schrieb:


    Und dann ist vorteilhaft - na eiglich erforderlich, dass man mit Drawing2D.Graphicspath und Drawing2D.Matrix umgehen kann, sonst macht man sich nur schwer.


    Inwieweit das für mich relevant ist konnte ich noch nicht feststellen.
    Dient es der Positionierung der Tasten?

    Mithilfe des oben genannten Tutorials habe ich mir folgende Control Klasse geschrieben:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.ComponentModel
    2. Public Class KeyboardKey : Inherits System.Windows.Forms.Control
    3. Public Enum KeyStatus
    4. KeyNotPressed = 1
    5. KeyIsPressing = 2
    6. KeyPressed = 3
    7. End Enum
    8. Dim mStatus As KeyStatus = KeyStatus.KeyNotPressed
    9. Dim mText As String
    10. Public Event StatusChanged(ByVal NewStatus As KeyStatus)
    11. <DefaultValue(KeyStatus.KeyNotPressed)> _
    12. Public Property Status() As KeyStatus
    13. Get
    14. Status = mStatus
    15. End Get
    16. Set(ByVal Value As KeyStatus)
    17. If mStatus <> Value Then
    18. mStatus = Value
    19. RaiseEvent StatusChanged(mStatus)
    20. Me.Invalidate()
    21. End If
    22. End Set
    23. End Property
    24. Public Overrides Property Text As String
    25. Get
    26. Return mText
    27. End Get
    28. Set(ByVal Value As String)
    29. mText = Value
    30. Me.Invalidate()
    31. End Set
    32. End Property
    33. Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    34. MyBase.OnPaint(e)
    35. Dim grfGraphics As System.Drawing.Graphics
    36. grfGraphics = e.Graphics
    37. Dim BrushText As New SolidBrush(Color.White)
    38. Dim ColorKey As Color
    39. Dim Font As New Font("Arial", 8)
    40. Select Case Status
    41. Case KeyStatus.KeyNotPressed
    42. ColorKey = Color.Black
    43. Case KeyStatus.KeyIsPressing
    44. ColorKey = Color.Red
    45. Case KeyStatus.KeyPressed
    46. ColorKey = Color.Green
    47. End Select
    48. Dim BrushRectangle As New SolidBrush(ColorKey)
    49. grfGraphics.FillRectangle(BrushRectangle, 0, 0, 100%, 100%)
    50. grfGraphics.DrawString(Text, Font, BrushText, 0, 0)
    51. ' Die Zeichnungsobjekte löschen.
    52. BrushText.Dispose()
    53. BrushRectangle.Dispose()
    54. Font.Dispose()
    55. grfGraphics.Dispose()
    56. End Sub
    57. Private Sub KeyboardKey_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Resize
    58. Me.Invalidate()
    59. End Sub
    60. End Class



    Tasten sind nicht schön, aber erstmal funktionell.
    Jetzt ist natürlich die Frage, wie ich die Tasten positioniere, wenn ich das Fenster (die Form) skalierbar haben möchte.
    Was wäre die geeignetste Möglichkeit?
    ja, ok, das ist ja "ein etwas anderer Ansatz", da kommste offsichtlich auch ohne das Drawing2D-Instrumentarium aus.
    Halt um den Preis, dass du für jede Taste ein eigenes Control aufwenden musst (sind glaub > 100). Meine Vorstellung war eher, für die Gesamt-Tastatur ein einziges Control aufzuwenden, und alle Tasten darauf selbst zu zeichnen.
    Aber ich will dir nix einreden, mein Ansatz ist nicht ganz einfach.
    Vorzüge hat er im Bereich Resourcen-Schonung und Performance, zB kann ich mir vorstellen, dass deine 100 Controls beim Resizen ziemlich träge reagieren - falls du eine flexible Größe ühaupt unterstützt.