Bilder zur Laufzeit anzeigen und wieder entfernen => Keine PictureBox

  • VB.NET

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Kagurame.

    Bilder zur Laufzeit anzeigen und wieder entfernen => Keine PictureBox

    Hallo,

    ich möchte zur Laufzeit in einer Forms-Anwendung Bilder anzeigen können und diese auch wieder von der Form löschen können.
    Ich möchte dabei ohne PictureBoxen arbeiten, da ich unter umständen mehrere Bilder übereinander habe und .Net dabei einige diverse Transparenz-Defizite hat was Controls angeht.

    Bild anzeigen habe ich über Graphics-Objekt hinbekommen, jedoch nur im OnPaint-Event oder per Control#CreateGraphics. Wie kann ich ein Bild ohne dieses anzeigen?
    Mit Control#CreateGraphics habe ich kein Problem, sofern ich irgendwie vorher gezeichnete Grafiken loswerde, ohne alles neu zeichnen zu müssen.

    Wie kann ich ein Bild, dass bereits anzeigt, einfach wieder löschen? Ich habe kein Problem, neue Objekte dafür zu erstellen / programmieren, aber ich habe derzeit keinen Ansatz wie es funktionieren könnte.

    Mit OnPaint müsste ich immer wieder die Form neu zeichnen lassen, was unschön anzusehen ist, wenn bestimmte Grafiken gehovert dargestellt werden sollen :/
    Hi
    schreib' dir ein eigenes Control und füge die Bilder in einer Liste ein, die wiederum das Neuzeichnen per Invalidate aufruft, sofern eine Änderung eintritt. Wenn du in einen Puffer (BufferedGraphics oder vorzugsweise Bitmap) zeichnest und diesen dann darstellst, musst du auch nicht jedes mal alle Bilder zeichnen. Die Liste kann bspw. von System.Collections.ObjectModel.Collection(Of T) erben und InsertItem, RemoveItem, SetItem und ClearItems überschreiben. Wenn du ihr dann eine Instanz des Controls übergibst, kannst du das Control über Änderungen informieren. CreateGraphics ist in diesem Fall nicht sinnvoll möglich, daher überschreib die OnPaint-Methode des geerbten Controls und füg' da die Zeichenoperationen ein. Für die Optimierung mit dem Zwischenpuffer gehst du einfach alle Bitmaps durch und ermittelst die maximale Größe. Danach legst du den Puffer entsprechend an und zeichnest darauf. Wenn du damit fertig bist, stellst du den Puffer auf e.Graphics dar.

    Gruß
    ~blaze~
    Eine Fläche löschen kannst Du so:

    VB.NET-Quellcode

    1. Private Sub Form1_Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
    2. e.Graphics.Clear(Color.Beige) ' Deine Farbe natürlich
    3. End Sub
    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!
    Naja, hab mal auf Basis dessen was gebastelt, was bisher recht sauber läuft und sich vernünftig handlen lässt. Danke.

    Edit:

    Habe das ganze mal etwa nach blazes Muster erstellt, was auch soweit funktioniert hat - bisher.

    Jetzt fällt im Nachhinein auf, dass die Größe der Bilder nicht stimmt ._.
    Wie kann ich Bilder skalieren bzw. verhindern, dass VB automatisch Bilder skaliert?

    In dem Screenshot (Siehe Link) geht es dabei um das runde etwas auf der rechten Seite, welches eine Größe von 760 auf 595 px hat - Das Control selbst hat die selbe Größe.
    Normalerweise sollte das runde etwas mittig angezeigt werden :/

    Bild
    Ein Teil des Codes:

    Spoiler anzeigen

    Control

    VB.NET-Quellcode

    1. Option Compare Binary
    2. Option Explicit On
    3. Option Strict On
    4. Option Infer On
    5. Imports System.Drawing
    6. Public Class GraphicsControl
    7. Private _lastColor As Color = Me.BackColor
    8. Private _images As New Dictionary(Of OsuImage, Boolean)
    9. Private _inForeGround As OsuImage
    10. Private _actions As New Dictionary(Of String, ActionType)
    11. Public Sub MakeTransparent()
    12. If Me.BackColor = Color.Transparent Then Return
    13. _lastColor = Me.BackColor
    14. Me.BackColor = Drawing.Color.Transparent
    15. End Sub
    16. Public Sub MakeInTransparent()
    17. Me.BackColor = _lastColor
    18. End Sub
    19. Public Sub MakeInTransparent(ByVal c As Color)
    20. _lastColor = c
    21. MakeInTransparent()
    22. End Sub
    23. Public Sub Add(ByVal image As OsuImage)
    24. If Include(image.Name) Then Return
    25. _images.Add(image, True)
    26. Draw(image)
    27. End Sub
    28. Public Sub BringToForeGround(ByVal name As String)
    29. If Not Include(name) Then Return
    30. Dim osImg As OsuImage = (From img As OsuImage In _images.Keys Where img.Name.Equals(name))(0)
    31. If Not _images(osImg) Then Return
    32. If _inForeGround.Name.Equals(osImg.Name) Then Return
    33. Draw(name)
    34. End Sub
    35. Public Sub Remove(ByVal name As String)
    36. If Not Include(name) Then Return
    37. Dim osImg As OsuImage = (From img As OsuImage In _images.Keys Where img.Name.Equals(name))(0)
    38. Dim isVisible As Boolean = _images(osImg)
    39. _images.Remove(osImg)
    40. If _actions.ContainsKey(name) Then _actions.Remove(name)
    41. If isVisible Then Refresh()
    42. End Sub
    43. Public Sub BlendOut(ByVal name As String)
    44. If Not Include(name) Then Return
    45. Dim osImg As OsuImage = (From img As OsuImage In _images.Keys Where img.Name.Equals(name))(0)
    46. Dim isVisible As Boolean = _images(osImg)
    47. _images(osImg) = False
    48. If isVisible Then Refresh()
    49. End Sub
    50. Public Sub BlendIn(ByVal name As String)
    51. If Not Include(name) Then Return
    52. Dim osImg As OsuImage = (From img As OsuImage In _images.Keys Where img.Name.Equals(name))(0)
    53. Dim isVisible As Boolean = _images(osImg)
    54. _images(osImg) = True
    55. If Not isVisible Then Draw(name)
    56. End Sub
    57. Public Sub AddAction(ByVal name As String, ByVal act As Action)
    58. If Not Include(name) Then Return
    59. Dim osImg As OsuImage = (From img As OsuImage In _images.Keys Where img.Name.Equals(name))(0)
    60. Dim action As New ActionType With {.Name = name, .Action = act, .Loc = osImg.Loc, .Size = osImg.Img.Size}
    61. _actions.Add(name, action)
    62. End Sub
    63. Private Function Include(ByVal name As String) As Boolean
    64. Dim imgs = From img As OsuImage In _images.Keys Where img.Name.Equals(name)
    65. Return imgs.Count > 0
    66. End Function
    67. Private Sub Draw(ByVal name As String)
    68. Dim images = From img As OsuImage In _images.Keys Where img.Name.Equals(name)
    69. Dim osImg As OsuImage = images(0)
    70. Draw(osImg)
    71. End Sub
    72. Private Sub Draw(ByVal osImg As OsuImage)
    73. Dim g As Graphics = Me.CreateGraphics
    74. g.DrawImage(osImg.Img, osImg.Loc)
    75. _inForeGround = osImg
    76. End Sub
    77. Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
    78. MyBase.OnPaint(e)
    79. Dim inForeGround As OsuImage = Nothing
    80. For Each osImg In _images
    81. If osImg.Value Then
    82. e.Graphics.DrawImage(osImg.Key.Img, osImg.Key.Loc)
    83. inForeGround = osImg.Key
    84. End If
    85. Next
    86. _inForeGround = inForeGround
    87. End Sub
    88. Protected Overrides Sub OnMouseClick(ByVal e As System.Windows.Forms.MouseEventArgs)
    89. MyBase.OnMouseClick(e)
    90. Dim mPos As New Point(MousePosition.X, MousePosition.Y)
    91. Dim point As Point = Osu.Business.OsuGraphics.GetRealPosition(Me)
    92. For Each actName As String In _actions.Keys
    93. If Not _images((From img As OsuImage In _images.Keys Where img.Name.Equals(actName))(0)) Then Continue For
    94. Dim actType As ActionType = _actions(actName)
    95. Dim realPoint As Point = New Point(point.X + actType.Loc.X, point.Y + actType.Loc.Y)
    96. Dim rect As New Rectangle(realPoint, actType.Size)
    97. If rect.Contains(mPos) Then actType.Action.Invoke()
    98. Next
    99. End Sub
    100. End Class
    101. Public Structure ActionType
    102. Public Name As String
    103. Public Action As Action
    104. Public Loc As Point
    105. Public Size As Size
    106. End Structure
    107. Public Structure OsuImage
    108. Public Name As String
    109. Public Img As Image
    110. Public Loc As Point
    111. Public ScaleSize As Size
    112. End Structure

    Hinzufügen des Bildes auf einem bestehenden Control

    VB.NET-Quellcode

    1. GCDrawingArea.Add(New OsuImage With {.Name = "Background", .Loc = New Point(0, 0), .Img = Image.FromFile(Menus.GetFileName(EMenus.Welcome_menu_))})

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