WM_NCHITTEST verändert Z-Order / SWP_NOZORDER hat keinen Effekt

Shakie

Erfahrenes Mitglied
Hallo,
ich möchte ein Control schreiben, bei dem der Benutzer mit der Maus die Größe des Controls verändern kann.
Dazu fange ich in WndProc die WM_NCCALCSIZE-Nachricht ab und setze das Ergebnis (m.Result) zum Beispiel auf HTLEFT, damit der Benutzer den linken Rand verschieben kann.
Das funktioniert auch soweit ganz gut. (Code siehe unten, kommt teilweise aus diesem Beispiel)
Das Ganze hat aber einen Haken: Windows verändert die Z-Order des Controls, wodurch mein ganzes Layout durcheinander kommt. Die Z-Reihenfolge wird derart verändert, dass das Control nun Z-Order Null hat (also selber Effekt wie Control.BringToFront).
Daraufhin wollte ich auch nocht WM_WINDOWPOSCHANGING abfangen und den Flag SWP_NOZORDER setzen, damit die Z-Order-Reihenfolge beibehalten wird. Aber das setzen des Flags bewirkt einfach gar nichts. Ich merke keine Veränderung im Verhalten, egal ob ich den Flag setze oder nicht. Hier der gesamte Code:
Code:
Imports System.Runtime.InteropServices
Public Class ResizableControl
    Inherits Control

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        Const Randbreite As Integer = 10
        Dim LeftR As New Rectangle(0, Randbreite, Randbreite, Me.Height - 2 * Randbreite)
        If m.Msg = WM_Messages.WM_NCHITTEST Then
            ' Position des Mauszeigers auslesen
            Dim MausPos As Point = Me.PointToClient(New Point(m.LParam.ToInt32))
            ' Überprüfen, ob sich der Mauszeiger im linken Rand des Controls befindet
            ' (Analog Prüfungen, ob sich der Mauszeiger in einem anderen Rand befindet, habe ich weggekürzt)
            If LeftR.Contains(MausPos) And (Me.Dock = DockStyle.Right Or Me.Dock = DockStyle.None) Then
                ' Control links resizable machen
                m.Result = New IntPtr(WM_NCHITTEST.HTLEFT)
            Else
                MyBase.WndProc(m)
            End If
        ElseIf m.Msg = WM_Messages.WM_WINDOWPOSCHANGING Then
            Dim WindowPosition As Windowpos = DirectCast(Marshal.PtrToStructure(m.LParam, GetType(Windowpos)), Windowpos)
            Const SWP_NOZORDER As UInteger = &H4
            ' Flag zum Beibehalten der Z-Order setzen, was aber nicht funktioniert
            WindowPosition.flags = SWP_NOZORDER Or WindowPosition.flags
            Marshal.StructureToPtr(WindowPosition, m.LParam, True)
        Else
            MyBase.WndProc(m)
        End If
    End Sub

    Private Enum WM_Messages As Integer
        WM_NCHITTEST = &H84
        WM_WINDOWPOSCHANGING = &H46
    End Enum

    Public Structure Windowpos
        Public hwnd As IntPtr
        Public hwndInsertAfter As IntPtr
        Public x As Integer
        Public y As Integer
        Public cy As Integer
        Public flags As UInteger
    End Structure

    Private Enum WM_NCHITTEST As Integer
        HTBOTTOM = 15
        HTLEFT = 10
        HTRIGHT = 11
        HTTOP = 12
    End Enum
End Class
Kann mir jemand sagen, was ich falsch mache oder kennt jemand eine bessere Möglichkeit? Mein Ziel ist eigentlich nur ein Control, dessen Dock-Eigenschaft ich auf irgend einen Rand setze und der Benutzer dann mit der Maus die Größe des Controls verändern können soll.
 
Zuletzt bearbeitet:
Zurück