Eigenes Control (Winform) - Hintergrund transparent

  • VB.NET

Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Gonger96.

    Eigenes Control (Winform) - Hintergrund transparent

    Hallo.

    Ich habe vor, eine eigene Form zu programmieren.

    Jetzt habe ich jedoch ein Problem: an den Ecken ist die Form schwarz,
    obwohl ich die Hintergrundfarbe auf Transparent setze.




    Code:

    VB.NET-Quellcode

    1. Public Class StudioForm : Inherits Form
    2. Private EdgeTopLeft, EdgeTopRight, EdgeBottomLeft, EdgeBottomRight, FormBgCol As Bitmap
    3. Public Sub New()
    4. Me.Size = New Size(107, 95)
    5. Me.DoubleBuffered = True
    6. Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    7. Me.SetStyle(ControlStyles.FixedHeight, True)
    8. Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    9. Me.SetStyle(ControlStyles.ResizeRedraw, True)
    10. Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
    11. Me.BackColor = Color.Transparent
    12. EdgeTopLeft = My.Resources.StudioFormEdgeTopLeft
    13. EdgeTopRight = My.Resources.StudioFormEdgeTopRight
    14. EdgeBottomLeft = My.Resources.StudioFormEdgeBottomLeft
    15. EdgeBottomRight = My.Resources.StudioFormEdgeBottomRight
    16. FormBgCol = My.Resources.StudioFormBg
    17. End Sub
    18. Public Sub Redraw(ausgabe As Graphics)
    19. If Me.Width < 107 Then Me.Width = 107
    20. If Me.Height < 95 Then Me.Height = 95
    21. Dim gr As Graphics = ausgabe
    22. gr.Clear(Me.BackColor)
    23. gr.DrawImage(EdgeTopLeft, New Point(0, 0))
    24. gr.DrawImage(EdgeTopRight, New Point(Me.Width - EdgeTopRight.Width - 10, 0))
    25. gr.DrawImage(EdgeBottomLeft, New Point(0, Me.Height - EdgeBottomLeft.Height - 14))
    26. gr.DrawImage(EdgeBottomRight, New Point(Me.Width - EdgeBottomRight.Width - 10, Me.Height - EdgeBottomRight.Height - 14))
    27. Dim z1 As Brush = New SolidBrush(Color.FromArgb(0, 85, 120))
    28. Dim xcoor As Integer = EdgeTopLeft.Width + 10
    29. Dim vertrectsiz As Size = New Size(Me.Width - EdgeBottomLeft.Width - EdgeBottomRight.Width - 20, EdgeBottomLeft.Height + 15)
    30. gr.FillRectangle(z1, New Rectangle(New Point(xcoor, 0), vertrectsiz))
    31. gr.FillRectangle(z1, New Rectangle(New Point(xcoor, Me.Height - EdgeBottomLeft.Height - 14), vertrectsiz))
    32. gr.FillRectangle(z1, New Rectangle(New Point(0, EdgeTopLeft.Height), New Size(Me.Width, Me.Height - EdgeTopLeft.Height - EdgeTopRight.Height)))
    33. End Sub
    34. Protected Overrides Sub OnPaint(pevent As System.Windows.Forms.PaintEventArgs)
    35. Redraw(pevent.Graphics)
    36. End Sub
    37. End Class



    Kann mir jemand sagen, wie ich das hinbekomme?
    Indem du den Nonclientbereich selbst renderst (gucke WM_NCPAINT). Zusätzlich kannst du noch die Form des NC-Bereiches wählen und per Form.Region setzen. Sowas ist aber relativ kompliziert und sieht schnell unserös aus. Visual Studio > 2012 macht das auch.
    Form unterstützt übrigens keine Transparenz, deshalb kann es nicht gehen, da Du davon erbst.

    VB.NET-Quellcode

    1. Me.DoubleBuffered = True
    2. Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    3. Me.SetStyle(ControlStyles.FixedHeight, True)
    4. Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    5. Me.SetStyle(ControlStyles.ResizeRedraw, True)
    6. Me.SetStyle(ControlStyles.SupportsTransparentBackColor, True)
    7. Me.BackColor = Color.Transparent


    Das ist auch Schwachsinn, ruf das ein einziges Mal auf, indem Du mit Or trennst. Übrigens, warum setzt Du DoubleBuffer dann überhaupt 2 mal? Ruf danach auch noch UpdateStyles auf.
    #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 :!:
    Klar geht das. Visual Studio malt seinen NC-Bereich selbst (das Programm selbst), das war nur ein Beispiel. So kompliziert ist es auch wieder nicht, du malst halt nicht im Paint-Event sondern fügst ebend OnNcPaint + NcPain(Event) hinzu und malst dort. Zusätzlich noch auf NCHITTEST und Co antworten und fertig. Musst du einfach mal nach suchen.

    Gonger96 schrieb:

    Klar geht das

    Nicht der NonClient-Aero-Bereich, komplette Transparenz. Das geht nicht. Kann man ja auch im Designer bei ner Form nicht einstellen.
    #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 :!:
    Also man findet hunderte von Leuten, die damit Probleme haben..

    Ich hab jetzt was gefunden, allerdings funktioniert es nicht (sollte eine Linie im Nonclient - Area zeichnen).

    VB.NET-Quellcode

    1. Imports System.Windows.Forms, System.Runtime.InteropServices, System.Drawing
    2. Module Module1
    3. Sub Main()
    4. Application.Run(New Windoww())
    5. Console.ReadKey()
    6. End Sub
    7. Public Class Windoww : Inherits Form
    8. <DllImport("User32.Dll")> Private Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
    9. End Function
    10. <DllImport("User32.Dll")> Private Shared Function ReleaseDC(hWnd As IntPtr, hDC As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    11. End Function
    12. Protected Overrides Sub WndProc(ByRef m As Message)
    13. MyBase.WndProc(m)
    14. If m.Msg = &H85 Then
    15. Console.WriteLine("Springt in den Block")
    16. Dim hDc As IntPtr = GetWindowDC(m.HWnd)
    17. Dim g As Graphics = Graphics.FromHdc(hDc)
    18. g.DrawLine(Pens.Red, 10, 10, 50, 10)
    19. g.Dispose()
    20. ReleaseDC(m.HWnd, hDc)
    21. End If
    22. End Sub
    23. End Class
    24. End Module


    Scheint ziemlich schwierig zu sein, damit was hinzubekommen.

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

    Habe jetzt neuen Code:

    VB.NET-Quellcode

    1. Imports System.Windows.Forms, System.Runtime.InteropServices, System.Drawing
    2. Module Module1
    3. Sub Main()
    4. Application.Run(New Windoww())
    5. Console.ReadKey()
    6. End Sub
    7. Public Class Windoww : Inherits Form
    8. <DllImport("User32.Dll")> Private Shared Function GetWindowDC(hWnd As IntPtr) As IntPtr
    9. End Function
    10. Protected Overrides Sub WndProc(ByRef m As Message)
    11. If m.Msg = &H83 Then
    12. Dim point As New Point(m.LParam.ToInt32())
    13. m.Result = New IntPtr(-1)
    14. Return
    15. End If
    16. Dim g As Graphics = Graphics.FromHwnd(Handle)
    17. g.DrawString("Test", New Font("Lucida Console", 10.0F), New SolidBrush(Color.FromArgb(0, 85, 120)), PointF.Empty)
    18. MyBase.WndProc(m)
    19. End Sub
    20. End Class
    21. End Module

    Das funktioniert, aber wie bekomme ich den Non-Client Bereich nun transparent?
    Falls sich noch keine Lösung gefunden hat.
    Falls es um die Form geht, da gibt es den Wert "TransparencyKey".
    Trage dort eine Farbe ein. und die Gleiche Farbe als Hintergrundfarbe.
    Überall wo diese Farbe auftaucht, wird sie nun Transparenz dargestellt.

    Jedoch... du solltest eine Farbe nehmen, die sonst nirgens auftaucht (schwarz ist z.B. keine gute Wahl), denn wenn du dann schwarzen Text schreibst,
    ist dieser auch Transparent und deine Form hat Löcher :)
    Nimm Fuchsia (wird oft dafür verwendet), Magenta oder halt irgend eine "exotische" Farbe.
    Sowas wär wieder unschön. Du musst nur den NonClientbereich selbst malen, alles andere bleibt so. Controls oder was auch immer im Clientbereich ist wird wie sonst auch gemalt. Für alles andere ist das nicht gedacht, da musst du zu WPF greifen. Es gibt genug Artikel dazu, ich werde dir nicht auch noch das Suchen abnehmen.