Fenstermanipulator bei transparentem Fenster.

  • VB.NET

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

    Fenstermanipulator bei transparentem Fenster.

    Hallo,

    meine "transparente" Fenster weisen ein (für mich) seltsames Verhalten an den Tag.

    Es werden vom Hauptfenster 2 Sub-Fenster angezeigt, und mit

    VB.NET-Quellcode

    1. Me.TransparencyKey = Color.FromName("Control")

    wird das Fenster transparent gemacht.
    (Damit der Rand des Fenster sichtbar wird zeichne ich noch mit Graphics ein Rechteck in der Form, ändert aber am Verhalten nichts)

    So bald diese Transparenz wirksam ist, und das Sub-Fenster sich teilweise auserhalb des Haupfenster ist, kann das Fenster nur noch bedingt in der Größe geänder werden.
    Wenn man mit der Maus an die untere rechte Ecke fährt, wird der "Fenstermanipulator" nicht richtig angezegt.
    Er erscheint nur wenn man mit der Maus schon etwas weiter vom Fenster entfernt ist, und auch nur gefühlt für ein Bereich von einem Pixel.

    An den anderen Ecken ist das Verhalten wie gewhohnt, und auch wenn die Transparenz ausgeschalten wird, geht es wieder.

    Da ich das Verhalten nur schwer erklären kann hab ich ein kleines Vidoe bei Reddit hochgeladen.
    (hoffe das ist kein Problem)

    Ergänzung: habe es bei .NET Framework 4.5.2 und 4.8 getestet.
    Kennt jemand das Problem oder hat eine Idee wie man es lösen könnte?

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

    SoEinVBler schrieb:

    (hoffe das ist kein Problem)
    Besser istz es, Du lädtst das Projekt in einer abgespeckten Form hoch, das können wir dann direkt in unser Studio laden.
    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!
    Transparenzen und Forms sind keine schöne Kombination. Auch Mouse-Events sind so eine Sache. Wo nichts sichtbar ist, kommen keine MouseEvents an, bzw. dort werden keine ausgelöst. Mach mal ein transparentes leeres Form, abonniere das MouseMove-Event und du wirst sehen dass dieses Abo ein Betrug ist, du wirst nicht beliefert :D . Du kannst ja auch durch das Form durchklicken, da wird also irgendwo das Problem entstehen. Ich wüsste da nur das Resizen selbt zu managen, das setzt aber vorraus die Maus zu tracken, wenn das Fenster den Focus hat.

    SoEinVBler schrieb:

    Color.FromName("Control")

    Geht besser: TransparencyKey = SystemColors.Control;

    SoEinVBler schrieb:

    "Fenstermanipulator"


    Das Ding nennt man Cursor, wird nur ein anderer angezeigt, probier mal das aus: [tt]Cursor = Cursors.SizeNS;
    Zitat von mir 2023:
    Was interessiert mich Rechtschreibung? Der Compiler wird meckern wenn nötig :D

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

    Ja, ist schon komisch, dass links und oben das Form veränderbar ist, unten und rechts nur, wenn man das Größenänderungsdreieck in der Ecke erwischt.

    @-Franky-: Um mal den WinForms-Compiler zu zitieren: Das Steuerelement unterstützt keine transparenten Hintergrundfarben.

    ##########

    Ich hab's mal bei Microsoft gemeldet, mal sehen, was da kommt. Wahrscheinlich: zur Kenntnis genommen, aber nicht wichtig genug.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

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

    VaporiZed schrieb:

    Um mal den WinForms-Compiler zu zitieren: Das Steuerelement unterstützt keine transparenten Hintergrundfarben.
    Oha, jau, mein Fehler. Dann kann ich noch folgendes anbieten: stackoverflow.com/questions/51…ckcolor-in-a-windows-form oder direkt per API SetWindowCompositionAttribute. Ersteres ist wohl aber besser (ungetestet).
    Auf die schnelle zusammengeklöppelt.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Private Enum WindowCompositionAttribute As Integer
    4. WCA_ACCENT_POLICY = &H13
    5. End Enum
    6. Private Enum AnimationId As Integer
    7. None = &H0
    8. End Enum
    9. Private Enum AccentFlags As Integer
    10. Draw00 = &H0
    11. Draw01 = &H1
    12. Draw02 = &H2
    13. Draw04 = &H4
    14. Draw08 = &H8
    15. Draw10 = &H10
    16. DrawLeftBorder = &H20
    17. DrawTopBorder = &H40
    18. DrawRightBorder = &H80
    19. DrawBottomBorder = &H100
    20. DrawAllBorders = DrawLeftBorder Or DrawTopBorder Or DrawRightBorder Or DrawBottomBorder
    21. End Enum
    22. Private Enum AccentState As Integer
    23. ACCENT_DISABLED = &H0
    24. ACCENT_ENABLE_GRADIENT = &H1
    25. ACCENT_ENABLE_TRANSPARENTGRADIENT = &H2
    26. ACCENT_ENABLE_BLURBEHIND = &H3
    27. ACCENT_ENABLE_ACRYLICBLURBEHIND = &H4
    28. ACCENT_ENABLE_HOSTBACKDROP = &H5
    29. ACCENT_ENABLE_TRANSPARENT = &H6
    30. ACCENT_INVALID_STATE = &H7
    31. End Enum
    32. Private Structure GradientColor
    33. Dim R As Byte
    34. Dim G As Byte
    35. Dim B As Byte
    36. Dim A As Byte
    37. End Structure
    38. Private Structure AccentPolicy
    39. Dim eAccentState As AccentState
    40. Dim eAccentFlags As AccentFlags
    41. Dim tGradientColor As GradientColor
    42. Dim eAnimationId As AnimationId
    43. End Structure
    44. Private Structure WindowCompositionAttributeData
    45. Dim Attribute As WindowCompositionAttribute
    46. Dim Data As IntPtr
    47. Dim SizeOfData As Integer
    48. End Structure
    49. <DllImport("user32.dll", EntryPoint:="SetWindowCompositionAttribute")>
    50. Private Shared Function SetWindowCompositionAttribute(<[In]> hwnd As IntPtr,
    51. <[In]> ByRef Data As WindowCompositionAttributeData) As Integer
    52. End Function
    53. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    54. Me.BackColor = Color.Black
    55. End Sub
    56. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    57. Dim accentPolicy As AccentPolicy
    58. Dim gradientColor As GradientColor
    59. Dim windowCompositionAttributeData As WindowCompositionAttributeData
    60. With gradientColor
    61. .A = 0
    62. .R = 0
    63. .G = 0
    64. .B = 0
    65. End With
    66. With accentPolicy
    67. .eAccentState = AccentState.ACCENT_ENABLE_TRANSPARENT
    68. .tGradientColor = gradientColor
    69. .eAccentFlags = AccentFlags.DrawAllBorders
    70. .eAnimationId = 0
    71. End With
    72. Dim sizeOfAccentPolicy As Integer = Marshal.SizeOf(accentPolicy)
    73. Dim pnt As IntPtr = Marshal.AllocHGlobal(sizeOfAccentPolicy)
    74. Marshal.StructureToPtr(accentPolicy, pnt, False)
    75. With windowCompositionAttributeData
    76. .Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY
    77. .SizeOfData = sizeOfAccentPolicy
    78. .Data = pnt
    79. End With
    80. Debug.Print(SetWindowCompositionAttribute(Me.Handle, windowCompositionAttributeData).ToString)
    81. Marshal.FreeHGlobal(pnt)
    82. End Sub
    83. Private Sub Form1_Click(sender As Object, e As EventArgs) Handles Me.Click
    84. Debug.Print("MouseClick")
    85. End Sub
    86. End Class



    Mfg -Franky-
    Vielen Dank schon mal für die Antworten.

    Ok, wenn keine MouseEvents im transparenten Fenster ankommen, könnte das eine Ursache sein, dass der Rand nicht richtig erkannt wird.(Spekulation)
    Aber warum es dann geht wenn es das transparente Fenster vor dem Hauptfenster ist, ist schon ein Rätsel.
    Bin ja mal gespannt ob von Microsoft eine Antwort kommt

    Dass die Mausevents nicht ankommen und man durch die transparente Form klicken kann ist in meinem Fall eigentlich ganz reizvoll.

    @-Franky- das Beispiel funktionier und da treten die Problem nicht auf, aber ich verliere auch die Möglichkeit "durch" die Form zu klicken.
    Ich muss mir das Beispiel aber noch genau anschauen um nachzuvollziehen was genau geschieht.
    Hallo,

    ich habe noch etwas mit den Hintergrundfarben für die Transparenz gespielt.
    Auch hier sind mir noch ein paar selstsame Dinge aufgefallen.
    Bei unterschiedlichen Farben reagiert die Form anders.
    1. Bei Grau- und z.B. Grüntönen kann man durch die Form klicken, und es kommt auch zu dem vorher benanten Effekt.
    2. Bei anderen Farben ist die Form zwar transparent, aber man kann nicht durch die Form durchklicken (MouseEvents kommen)
    3. Bei schwarzer Farbe kann die Form auch nich mehr über die Titelleiste verschoben werden oder beendet werden. Die Titelleiste mit X ist wie deaktiviert.

    Dann hab ich noch mit der Rahmengröße, welchen ich in der Form zeichne, um diese besser sichtbar zu machen, gespielt.

    Wenn ich den Rand auf 10 oder höher setzte geht das Vergrößern an den Seiten bis zu den Ecken, aber in der Mitte unten geht es immer noch nicht...
    Ab einem Rand von ca. 30 geht es auch unten wieder.
    (Sieht halt nich schön aus)

    Die MausEvents kommen in dem Rahmen teilweise, Richtung Mitte der Form gehen sie irgendwann nich mehr, und im unteren Bereich ist es noch schlechter.

    Hier noch mein Beispiel Code.


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private stiftbreite As Int16 = 4
    3. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    4. Me.BackColor = Color.Green
    5. 'Me.BackColor = Color.Blue
    6. 'Me.BackColor = Color.Black
    7. Me.TransparencyKey = Me.BackColor
    8. Me.TopMost = True
    9. Me.FormBorderStyle = FormBorderStyle.SizableToolWindow
    10. End Sub
    11. Private Sub Form1_MouseClick(sender As Object, e As MouseEventArgs) Handles Me.MouseClick
    12. Debug.Print("Mauscklick")
    13. End Sub
    14. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    15. Debug.Print("Mausmove")
    16. End Sub
    17. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    18. Dim stift As New Pen(Brushes.OrangeRed, stiftbreite)
    19. e.Graphics.DrawRectangle(stift, stift.Width / 2, stift.Width / 2, Me.ClientRectangle.Width - stift.Width, Me.ClientRectangle.Height - stift.Width)
    20. End Sub
    21. Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    22. Me.Invalidate()
    23. End Sub
    24. End Class
    Hi. Evtl. sollte man wissen das wenn TransparencyKey und/oder Opacity verwendet werden, intern der Form der WindowsStyle WS_EX_LAYERED (oder auch WS_EX_TRANSPARENT) hinzugefügt werden (GetWindowLong/SetWindowLong). Bei WS_EX_LAYERED kommt dann noch die API SetLayeredWindowAttributes mit Flags LWA_COLORKEY (Eigenschaft TransparencyKey) und/oder LWA_ALPHA (Eigenschaft Opacity) zum Einsatz. Im groben schaut das intern dann so aus.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. Private Const GWL_EXSTYLE As Integer = (-20)
    4. Private Const WS_EX_LAYERED As Integer = &H80000
    5. Private Const LWA_COLORKEY As Integer = &H1
    6. Private Const LWA_ALPHA As Integer = &H2
    7. <DllImport("user32.dll", EntryPoint:="GetWindowLong")>
    8. Private Shared Function GetWindowLong(<[In]> hwnd As IntPtr,
    9. <[In]> nIndex As Integer) As Integer
    10. End Function
    11. <DllImport("user32.dll", EntryPoint:="SetWindowLong")>
    12. Private Shared Function SetWindowLong(<[In]> hwnd As IntPtr,
    13. <[In]> nIndex As Integer,
    14. <[In]> dwNewLong As Integer) As Integer
    15. End Function
    16. <DllImport("user32.dll", EntryPoint:="SetLayeredWindowAttributes")>
    17. Private Shared Function SetLayeredWindowAttributes(<[In]> hwnd As IntPtr,
    18. <[In]> crKey As Integer,
    19. <[In]> bAlpha As Byte,
    20. <[In]> dwFlags As Integer) As Integer
    21. End Function
    22. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    23. e.Graphics.FillRectangle(Brushes.Black, 1, 1, 100, 100)
    24. End Sub
    25. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    26. SetWindowLong(Me.Handle, GWL_EXSTYLE, GetWindowLong(Me.Handle, GWL_EXSTYLE) Or WS_EX_LAYERED)
    27. SetLayeredWindowAttributes(Me.Handle, Color.Black.ToArgb, 255, LWA_COLORKEY Or LWA_ALPHA)
    28. End Sub
    29. End Class


    Allerdings ist das Verhalten unter .NET scheinbar ein wenig anderer als unter VB6 denn da funktioniert das wie es soll. Das wird (ungetestet) mit dem Manifest zusammenhängen da in .NET ja die Forms/Controls sich dem Theme von Windows anpassen. Ich würde aber auch sagen das es sich hier um einen Bug in .Net handelt.
    Mfg -Franky-
    Microsoft hat geantwortet: Mit Color.Red für BackColor und TransparencyKey funktioniert es (bei denen und mir) richtig. Aber: Bug bleibt Bug bleibt Fehler.
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Hallo,

    ich gehe mal davon aus, das richtige Verhalten ist, dass die MausEvents kommen und man nicht durch die transparente Form klicken kann.(macht ja eigentlich Sinn)
    Das klappt auch mit anderen Farben, Gelb, Blau oder Orange.
    Bei Grau- und Grüntönen ist es (bei mir) anders.

    Naja zumindest weiß man jetzt ungefär wie es sich verhält.

    SoEinVBler schrieb:

    ich gehe mal davon aus, das richtige Verhalten ist, dass die MausEvents kommen und man nicht durch die transparente Form klicken kann
    Das hängt davon ab welches Verfahren verwendet wird um einen transparenten Bereich in einer Form zu erzeugen. Per Region-APIs (z.B SetWindowRgn), per API SetLayeredWindowAttributes, per API SetWindowCompositionAttribute bzw. per DWM-APIs usw. .NET wird SetLayeredWindowAttributes mit entsprechenden WS_EX-Flags verwenden. Es ist dennoch ein Bug in .NET das unterschiedliche Farben ein unterschiedliches Verhalten hervor ruft.
    Mfg -Franky-
    Wie vermutet: Für Microsoft zu uninteressant. Es müssten da schon einige Leute voten, damit es eher angegangen wird, aber das hat ja bei früheren Problemen auch schon nicht funktioniert … :/
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    @SoEinVBler Falls Du das Fenster durchklickbar haben möchtest und dort wo Controls auf der Form sind nicht, dann wäre das per Region und GraphicsPath möglich. Allerding mit einem Nachteil, das Fenster wird im alten Style angezeigt.
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    3. Using OuterPath As New Drawing2D.GraphicsPath
    4. Using InnerPath As New Drawing2D.GraphicsPath
    5. Using CombinedPath As New Drawing2D.GraphicsPath
    6. Dim BorderSize As Integer = (Me.Width - Me.ClientSize.Width) \ 2
    7. Dim CaptionSize As Integer = Me.Height - Me.ClientSize.Height
    8. OuterPath.AddRectangle(New Rectangle(0, 0, Me.Width, Me.Height))
    9. InnerPath.AddRectangle(New Rectangle(BorderSize, CaptionSize - BorderSize,
    10. Me.ClientSize.Width, Me.ClientSize.Height))
    11. CombinedPath.AddPath(OuterPath, True)
    12. CombinedPath.AddPath(InnerPath, True)
    13. Using TransparentRegion As New Region(CombinedPath)
    14. For Each Ctrl As Control In Me.Controls
    15. If Ctrl.Container Is Me.Container Then
    16. TransparentRegion.Xor(New Rectangle(Ctrl.Location.X + BorderSize,
    17. Ctrl.Location.Y + (CaptionSize - BorderSize),
    18. Ctrl.Size.Width,
    19. Ctrl.Size.Height))
    20. End If
    21. Next
    22. Region = TransparentRegion
    23. End Using
    24. End Using
    25. End Using
    26. End Using
    27. End Sub
    28. End Class



    @VaporiZed Ich hatte auch mal was an MS gemeldet. Eigentlich ein Sicherheitsproblem beim laden älterer Officedateien (DOC, XLS, usw.) mit Makros obwohl das ausführen der Makros (VBA) untersagt ist. Die Makros wurden dennoch ausgeführt. X( Antwort von MS: This is by design. Ja dann. ?(
    Mfg -Franky-
    Also bei TransparencyKey=true wäre es für mich schon das Standardverhalten wenn die Form durchsichtig ist, aber die MausEvents kommen.
    (Durch meine durchsichtigen Fenster daheim kann ich auch nicht durch greifen)

    Das es sich bei Grau und Grün anders verhält ist klar ein Bug, aber für mich gerade ein netter Nebenefekt den ich nutze.
    Mit der Einschränkung die Größe rechts unten nicht so einfach einstellen zu können.(restlichen Ecken gehen ja)

    Mit Region-API hab ich getestet, aber dann sehen die Fenster wieder anders aus (ist das dann Win7?)
    Die anderen habe ich nicht versucht.

    Aktuell bleib ich bei TransparencyKey und lebe mit dem kleinen Nachteil.
    Aber danke schon mal für die genzen Tipps.



    Hallo,

    das mit den Region-API's hat mir doch keine Ruhe gelassen, und habe damit noch ein paar Tests gemacht.

    In meine Fenster habe ich nun ein Variable (useRegion) mit der ich wählen kann ob ich TransparencyKey oder lieber die Region-API' nutzen möchte.

    Wenn die Region-API 's genutzt werden ändert sich bei mir die Darstellung der Form, es ist dann nicht mehr die "flach" Form von "Win10"( oder was es ist), sondern hat einen "3D-Rand"
    Mit hilfe der Regionen schneide ich aber außen etwas vom Rand ab, zusätzlich setze ich trotzsem den TransparencyKey, und zwar aktuell auf die Farbe SystemColors.InactiveBorder
    Somit ist der Rahmen kleiner und nur bei aktivier Form sichtbar.
    Die Form kann aber ringsum vergrößert oder verkleinert werden.

    Hier noch 3 Bilder um den Vergleich zu sehen.



    Und hier der Code den ich verwende:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Private Declare Function CombineRgn Lib "gdi32" (ByVal hDestRgn As Integer, ByVal hSrcRgn1 As Integer, ByVal hSrcRgn2 As Integer, ByVal nCombineMode As Integer) As Integer
    3. Private Declare Function CreateRectRgn Lib "gdi32" (ByVal X1 As Integer, ByVal Y1 As Integer, ByVal X2 As Integer, ByVal Y2 As Integer) As Integer
    4. Private Declare Function SetWindowRgn Lib "user32" (ByVal hwnd As IntPtr, ByVal hRgn As Integer, ByVal bRedraw As Boolean) As Integer
    5. Private Const RGN_DIFF = 4
    6. Private useRegion As Boolean = False
    7. Private FormRand As Int16 = Convert.ToInt16(Math.Round((Me.Width - Me.ClientSize.Width) / 2, 0))
    8. Private Randverkleinern As Int16 = 4
    9. Private innererRahmen As Int16 = 4
    10. Private RahmenFarbe As Color = Color.Red
    11. Private innerSize As Rectangle
    12. Private TitelHoehe As Integer
    13. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    14. If useRegion Then
    15. getInnerSize()
    16. Me.BackColor = RahmenFarbe
    17. Me.TransparencyKey = SystemColors.InactiveBorder
    18. Else
    19. Me.BackColor = Color.Gray
    20. Me.TransparencyKey = Me.BackColor
    21. End If
    22. Me.FormBorderStyle = FormBorderStyle.SizableToolWindow
    23. Me.TopMost = True
    24. End Sub
    25. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    26. If useRegion Then
    27. Dim r1, r2 As Integer
    28. r1 = CreateRectRgn(Randverkleinern, Randverkleinern, Me.Width - Randverkleinern, Me.Height - Randverkleinern)
    29. r2 = CreateRectRgn(innerSize.Left, innerSize.Y, innerSize.Width, innerSize.Height)
    30. CombineRgn(r1, r1, r2, RGN_DIFF)
    31. SetWindowRgn(Me.Handle, r1, True)
    32. Else
    33. Dim stift As New Pen(RahmenFarbe, innererRahmen)
    34. e.Graphics.DrawRectangle(stift, stift.Width / 2, stift.Width / 2, Me.ClientRectangle.Width - stift.Width, Me.ClientRectangle.Height - stift.Width)
    35. End If
    36. End Sub
    37. Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    38. getInnerSize()
    39. If innerSize.Width - innerSize.Left <= 0 Then Me.Width = 1 + 2 * FormRand + 2 * innererRahmen
    40. If innerSize.Height - innerSize.Top <= 0 Then Me.Height = 1 + TitelHoehe + FormRand + 2 * innererRahmen
    41. Me.Invalidate()
    42. End Sub
    43. Private Sub getInnerSize()
    44. TitelHoehe = (Me.Height - Me.ClientSize.Height - FormRand)
    45. innerSize.X = FormRand + innererRahmen
    46. innerSize.Y = TitelHoehe + innererRahmen
    47. innerSize.Width = Me.Width - innererRahmen - FormRand
    48. innerSize.Height = Me.Height - innererRahmen - FormRand
    49. End Sub
    50. End Class



    Beiträge zusammengefügt. ~Thunderbolt

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

    Hi. Das mit der Region ist eher was für Forms mit BorderStyle = None. Dann zeichnet man sich den Border, die CaptionBar usw. selber. Forms mit BorderStyle = None zu verschieben und in der Größe zu verändern ist das kleinste Problem.

    Edit: Die Region-APIs brauchst nicht wirklich da das in .NET vorhanden ist (siehe dazu mein Bsp. mit GraphisPath und Region). Deine API-Deklarationen sind auch nicht korrekt. CreateRectRgn gibt ein Handle auf eine Region zurück (hRgn). Daher IntPtr. Entsprechend müssen dann bei CombineRgn alle hXxxRgn auch IntPtr sein und es fehlt die API DeleteObject um die erzeugte hRgn nach Gebrauch zu löschen (in .NET -> Dispose).
    Mfg -Franky-

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

    Hallo,

    @-Franky- ich muss gestehen, das mit deinem Beispiel ist mir irgendwie untergegangen.

    In einem vorherigen Post habe ich was mit API gelesen und mir gleich ein altes Beispiel von mir mit den API rausgezogen. (War damals unter Excel VBA)

    Das die Deklerationen nicht ganz stimmen war mir fast klar, da hänge ich immer... (muss ich irgendwann mal aufarbeiten)
    Das die Regionen auch wieder gelösch werden sollte ist mir auch aufgefallen, aber die API DeleteObject ist mir dazu nicht eingefallen, bzw. hab das bisher meißt vernachlässigt.
    (Ich hatte bei Microsoft nach den Regions-APIs geschaut aber so was wie DelRgn nicht gefunden...)


    Mit deinem Beispiel geht es natürlich auch, und ich denke das ist auch "Sicherer" wie mit API'S

    Aktuell teste ich nun mit BorderStyle = None und einem Label als "Titelleiste"
    Das Verschieben/Vergrößern bekomme ich zwar hin, vermute aber dass es da was einfacheres gibt.


    Bisher teste ich wo die Maus sich befindet, am Rand links, rechts, oben, unten, und setzte dann Variablen.
    Diese werte ich dann aus um entweder den Curser zu setzen oder die Form dann zu verchieben/vergrößern.

    Da das Label ganz oben über die ganze Formbreite geht habe ich den Code nun doppelt drin,einmal für das Label und dann die Form.
    Das würde ich jetzt noch versuchen in eine SUB zu bringen.
    Außerdem ist noch ein Bug drin, wenn die Form zu klein wird begrenze ich das zwar, aber dann geht das mit dem Vergrößern nicht mehr richtig...

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Public Class Form1
    2. Dim BorderSize As Integer = 10
    3. Dim CaptionSize As Integer
    4. Private MinSize As Int16 = 5
    5. Private tx As Integer = -1
    6. Private ty As Integer = -1
    7. Private fx As Integer = -1
    8. Private fy As Integer = -1
    9. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    10. Me.TopMost = True
    11. Me.FormBorderStyle = FormBorderStyle.None
    12. Me.BackColor = Color.Red
    13. lbTitel.Left = 0
    14. lbTitel.Top = 0
    15. lbTitel.Width = Me.Width
    16. lbTitel.Height = Math.Max(lbTitel.Height, BorderSize + 10)
    17. CaptionSize = lbTitel.Height
    18. End Sub
    19. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    20. Using OuterPath As New Drawing2D.GraphicsPath
    21. Using InnerPath As New Drawing2D.GraphicsPath
    22. Using CombinedPath As New Drawing2D.GraphicsPath
    23. OuterPath.AddRectangle(New Rectangle(0, 0, Me.Width, Me.Height))
    24. InnerPath.AddRectangle(New Rectangle(BorderSize, CaptionSize + BorderSize, Me.Width - 2 * BorderSize, Me.Height - 2 * BorderSize - CaptionSize))
    25. CombinedPath.AddPath(OuterPath, True)
    26. CombinedPath.AddPath(InnerPath, True)
    27. Using TransparentRegion As New Region(CombinedPath)
    28. Region = TransparentRegion
    29. End Using
    30. End Using
    31. End Using
    32. End Using
    33. End Sub
    34. Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    35. If Me.Width < MinSize + 2 * BorderSize Then Me.Width = MinSize + 2 * BorderSize
    36. If Me.Height < MinSize + CaptionSize + 2 * BorderSize Then Me.Height = MinSize + CaptionSize + 2 * BorderSize
    37. Me.Invalidate()
    38. End Sub
    39. Private Sub lbTitel_MouseMove(sender As Object, e As MouseEventArgs) Handles lbTitel.MouseMove
    40. Static Dim ou, lr As Integer
    41. If tx >= 0 Then
    42. If (lr = 0 And ou = 0) Or lr = -1 Then Me.Left += e.X - tx
    43. If lr <> 0 Then Me.Width += lr * (e.X - tx)
    44. If lr > 0 Then tx = e.X
    45. If ou = -1 Or (ou = 0 And lr = 0) Then Me.Top += e.Y - ty
    46. If ou <> 0 Then Me.Height += ou * (e.Y - ty)
    47. Else
    48. If e.X > lbTitel.Width - BorderSize Then
    49. lr = 1
    50. ElseIf e.X < BorderSize Then
    51. lr = -1
    52. Else
    53. lr = 0
    54. End If
    55. If e.Y < BorderSize Then ou = -1 Else ou = 0
    56. If ou = -1 Then
    57. If lr = 1 Then
    58. lbTitel.Cursor = Cursors.SizeNESW
    59. ElseIf lr = -1 Then
    60. lbTitel.Cursor = Cursors.SizeNWSE
    61. Else
    62. lbTitel.Cursor = Cursors.SizeNS
    63. End If
    64. Else
    65. If lr <> 0 Then
    66. lbTitel.Cursor = Cursors.SizeWE
    67. Else
    68. lbTitel.Cursor = Cursors.SizeAll
    69. End If
    70. End If
    71. End If
    72. End Sub
    73. Private Sub lbTitel_MouseDown(sender As Object, e As MouseEventArgs) Handles lbTitel.MouseDown
    74. tx = e.X
    75. ty = e.Y
    76. End Sub
    77. Private Sub lbTitel_MouseUp(sender As Object, e As MouseEventArgs) Handles lbTitel.MouseUp
    78. tx = -1
    79. ty = -1
    80. End Sub
    81. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    82. Static Dim ou, lr As Integer
    83. If fx >= 0 Then
    84. If (lr = 0 And ou = 0) Or lr = -1 Then Me.Left += e.X - fx
    85. If lr <> 0 Then Me.Width += lr * (e.X - fx)
    86. If lr > 0 Then fx = e.X
    87. 'If ou = 1 Then Me.Top += e.Y - ty
    88. If ou <> 0 Then Me.Height += ou * (e.Y - fy)
    89. If ou > 0 Then fy = e.Y
    90. Else
    91. If e.X > Me.Width - BorderSize Then
    92. lr = 1
    93. ElseIf e.X < BorderSize Then
    94. lr = -1
    95. Else
    96. lr = 0
    97. End If
    98. If e.Y > Me.Height - BorderSize Then ou = 1 Else ou = 0
    99. If ou = 1 Then
    100. If lr = 1 Then
    101. Me.Cursor = Cursors.SizeNWSE
    102. ElseIf lr = -1 Then
    103. Me.Cursor = Cursors.SizeNESW
    104. Else
    105. Me.Cursor = Cursors.SizeNS
    106. End If
    107. Else
    108. If lr <> 0 Then
    109. Me.Cursor = Cursors.SizeWE
    110. Else
    111. End If
    112. End If
    113. End If
    114. End Sub
    115. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    116. fx = e.X
    117. fy = e.Y
    118. End Sub
    119. Private Sub Form1_MouseUp(sender As Object, e As MouseEventArgs) Handles Me.MouseUp
    120. fx = -1
    121. fy = -1
    122. End Sub
    123. End Class


    Hi. Intern verwendet. NET auch die Region-APIs. Von daher ist es egal ob per API oder per .NET. Am Ende kommt das gleiche Ergebnis raus. ;)

    Form ohne Titelleiste bewegen: activevb.de/tipps/vbnettipps/tipp0045.html wobei auch hier die APIs nicht ganz korrekt sind. Falls Du das Systemmenü bei Form mit FormBorderStyle = None benötigst: activevb.de/tipps/vbnettipps/tipp0123.html Oha, mit Visual Studio 2005 mal gebastelt. Lang lang ist es her. :)
    Mfg -Franky-
    Da ich kein Systemmenü benötige reicht erst mal der 1. Tipp.
    Das spart schon einiges an Arbeit, jetzt geht bewegen und Größe ändern wie gewünscht.

    Falls es mal jemand brauchen kann, hier mein Code für ein transparentes Fester
    Das Fenster hat eine "Titeleiste" (Label) und einen Rahmen durch den man auch hindurchcklicken kann.
    Benutz werdenn kann es z.B. um anzuzeigen von welchem Bereich des Bildschrims ein Screenshot gemacht wird.

    Im Fenter ein Label hinzufügen und dieses in lbTitel umbenennen.




    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Runtime.InteropServices
    2. Public Class Form1
    3. <DllImport("user32.dll")>
    4. Private Shared Function ReleaseCapture() As Boolean
    5. End Function
    6. <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    7. Private Shared Function SendMessage(ByVal hWnd As IntPtr,
    8. ByVal Msg As UInteger,
    9. ByVal wParam As Integer,
    10. ByVal lParam As Integer) As Integer
    11. End Function
    12. Private Const HTNOWHERE As Short = 0
    13. Private Const HTCAPTION As Short = 2
    14. Private Const HTLEFT As Short = 10
    15. Private Const HTRIGHT As Short = 11
    16. Private Const HTTOP As Short = 12
    17. Private Const HTTOPLEFT As Short = 13
    18. Private Const HTTOPRIGHT As Short = 14
    19. Private Const HTBOTTOM As Short = 15
    20. Private Const HTBOTTOMLEFT As Short = 16
    21. Private Const HTBOTTOMRIGHT As Short = 17
    22. Private Const WM_NCLBUTTONDOWN As Short = &HA1S
    23. Private Const WM_SYSCOMMAND As Short = &H112S
    24. Private SizeMoveConst As Integer
    25. Private CaptionSize As Integer
    26. Private MinSize As Int16 = 5
    27. Private BorderSize As Short = 10
    28. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
    29. Me.TopMost = True
    30. Me.FormBorderStyle = FormBorderStyle.None
    31. Me.BackColor = Color.Red
    32. lbTitel.AutoSize = False
    33. lbTitel.BorderStyle = BorderStyle.FixedSingle
    34. lbTitel.Anchor = AnchorStyles.Left Or AnchorStyles.Top Or AnchorStyles.Right
    35. lbTitel.BackColor = SystemColors.ButtonHighlight
    36. lbTitel.TextAlign = ContentAlignment.MiddleLeft
    37. lbTitel.Text = Me.Text
    38. lbTitel.Left = 0
    39. lbTitel.Top = 0
    40. lbTitel.Width = Me.Width
    41. lbTitel.Height = Math.Max(lbTitel.Height, BorderSize + 20)
    42. CaptionSize = lbTitel.Height
    43. Me.Left = 500
    44. Me.Top = 500
    45. End Sub
    46. Private Sub Form1_TextChanged(sender As Object, e As EventArgs) Handles Me.TextChanged
    47. lbTitel.Text = Me.Text
    48. End Sub
    49. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    50. Using OuterPath As New Drawing2D.GraphicsPath
    51. Using InnerPath As New Drawing2D.GraphicsPath
    52. Using CombinedPath As New Drawing2D.GraphicsPath
    53. OuterPath.AddRectangle(Me.DisplayRectangle)
    54. InnerPath.AddRectangle(New Rectangle(BorderSize, CaptionSize + BorderSize, Me.Width - 2 * BorderSize, Me.Height - 2 * BorderSize - CaptionSize))
    55. CombinedPath.AddPath(OuterPath, True)
    56. CombinedPath.AddPath(InnerPath, True)
    57. Using TransparentRegion As New Region(CombinedPath)
    58. Region = TransparentRegion
    59. End Using
    60. End Using
    61. End Using
    62. End Using
    63. End Sub
    64. Private Sub Form1_Resize(sender As Object, e As EventArgs) Handles Me.Resize
    65. If Me.Width < MinSize + 2 * BorderSize Then Me.Width = MinSize + 2 * BorderSize
    66. If Me.Height < MinSize + CaptionSize + 2 * BorderSize Then Me.Height = MinSize + CaptionSize + 2 * BorderSize
    67. Me.Invalidate()
    68. End Sub
    69. Private Sub lbTitel_MouseMove(sender As Object, e As MouseEventArgs) Handles lbTitel.MouseMove
    70. lbTitel.Cursor = HitTest(e.Location)
    71. End Sub
    72. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    73. Me.Cursor = HitTest(e.Location)
    74. End Sub
    75. Private Sub lbTitel_MouseDown(sender As Object, e As MouseEventArgs) Handles lbTitel.MouseDown
    76. If SizeMoveConst <> 0 Then
    77. ReleaseCapture()
    78. SendMessage(Me.Handle, WM_NCLBUTTONDOWN, SizeMoveConst, 0)
    79. End If
    80. End Sub
    81. Private Sub Form1_MouseDown(sender As Object, e As MouseEventArgs) Handles Me.MouseDown
    82. If SizeMoveConst <> 0 Then
    83. ReleaseCapture()
    84. SendMessage(Me.Handle, WM_NCLBUTTONDOWN, SizeMoveConst, 0)
    85. End If
    86. End Sub
    87. Private Function HitTest(MouseCoord As Point) As Cursor
    88. Dim UpDownPos, LeftRightPos As Int16
    89. If MouseCoord.X > Me.Width - BorderSize Then
    90. LeftRightPos = 1
    91. ElseIf MouseCoord.X < BorderSize Then
    92. LeftRightPos = -1
    93. End If
    94. If MouseCoord.Y > Me.Height - BorderSize Then
    95. UpDownPos = 1
    96. ElseIf MouseCoord.Y < BorderSize Then
    97. UpDownPos = -1
    98. End If
    99. If UpDownPos = 1 Then
    100. If LeftRightPos = 1 Then
    101. HitTest = Cursors.SizeNWSE
    102. SizeMoveConst = HTBOTTOMRIGHT
    103. ElseIf LeftRightPos = -1 Then
    104. HitTest = Cursors.SizeNESW
    105. SizeMoveConst = HTBOTTOMLEFT
    106. Else
    107. HitTest = Cursors.SizeNS
    108. SizeMoveConst = HTBOTTOM
    109. End If
    110. ElseIf UpDownPos = -1 Then
    111. If LeftRightPos = 1 Then
    112. HitTest = Cursors.SizeNESW
    113. SizeMoveConst = HTTOPRIGHT
    114. ElseIf LeftRightPos = -1 Then
    115. HitTest = Cursors.SizeNWSE
    116. SizeMoveConst = HTTOPLEFT
    117. Else
    118. HitTest = Cursors.SizeNS
    119. SizeMoveConst = HTTOP
    120. End If
    121. Else
    122. If LeftRightPos = 1 Then
    123. HitTest = Cursors.SizeWE
    124. SizeMoveConst = HTRIGHT
    125. ElseIf LeftRightPos = -1 Then
    126. HitTest = Cursors.SizeWE
    127. SizeMoveConst = HTLEFT
    128. Else
    129. HitTest = Cursors.SizeAll
    130. SizeMoveConst = HTCAPTION
    131. End If
    132. End If
    133. End Function
    134. End Class

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