【问题标题】:Control Not move in drag and drop控制在拖放中不移动
【发布时间】:2023-03-20 04:39:01
【问题描述】:

在我的应用程序中,我想将控件从一侧移动到另一侧。 tablelayoutpanel里面的那个控件。我想拖动面板内的控件,而面板位于表格布局面板内,所以首先我删除了控件表单面板并在表单中添加控件,然后我拖动按钮控件使其问题无法清晰拖动。 (这意味着快速拖动它不能正常工作)。我的代码是

Private Sub HandleDraggableControlMouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Button2.MouseDown
    Dim target As Control = TryCast(sender, Control)
    Dim xWidth, xHeight As Integer

    If (Not target Is Nothing) Then

        xWidth = sender.Width
        xHeight = sender.Height
        sender.Parent.Controls.Remove(sender)
        sender.Dock = DockStyle.None

        sender.Width = xWidth
        sender.Height = xHeight
        Me.Controls.Add(sender)

        Dim pt As Point = Me.PointToClient(target.PointToScreen(Point.Empty))
        target.Location = pt
        target.Parent = Me
        target.BringToFront()
        Me.isMouseDown = True
        Me.cachedControlPos = pt
        Me.cachedMousePos = Control.MousePosition

    End If
End Sub

Private Sub HandleDraggableControlMouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Button2.MouseMove
    If (Me.isMouseDown) Then
        Dim target As Control = TryCast(sender, Control)
        If (Not target Is Nothing) Then
            Dim x As Integer = (Me.cachedControlPos.X + (Control.MousePosition.X - Me.cachedMousePos.X))
            Dim y As Integer = (Me.cachedControlPos.Y + (Control.MousePosition.Y - Me.cachedMousePos.Y))
            target.Location = New Point(x, y)

            'c2 = (c1 + (m2 - m1))

        End If
    End If
End Sub

Private Sub HandleDraggableControlMouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles Button2.MouseUp
    Me.cachedControlPos = Point.Empty
    Me.cachedMousePos = Point.Empty
    Me.isMouseDown = False
End Sub

我的问题是如果快速拖动控件,控件不移动光标只移动了为什么?我的编码做错了什么?问题如何解决?

【问题讨论】:

    标签: vb.net winforms drag-and-drop


    【解决方案1】:

    您需要将当前鼠标位置 m2 与缓存鼠标位置 m1 之间的差异添加到 缓存控件位置 c1 给你当前的控制位置c2

    c2 = (c1 + (m2 - m1))
    

    类似这样的:

    sender.Location = New Point(
        (cachedControlLocation.X + (e.X - startX)), 
        (cachedControlLocation.Y + (e.Y - startY))
    )
    

    这是一个示例表单,向您展示它是如何工作的:

    Public Class Form1
    
        Public Sub New()
            Me.InitializeComponent()
            Me.ClientSize = New Size(800, 600)
            Me.panel1 = New Panel() With {.Bounds = New Rectangle(10, 10, 300, 300), .BackColor = Color.Red}
            Me.panel2 = New Panel() With {.Bounds = New Rectangle(10, 10, 200, 200), .BackColor = Color.Green}
            Me.panel3 = New Panel() With {.Bounds = New Rectangle(10, 10, 100, 100), .BackColor = Color.Blue}
            Me.panel2.Controls.Add(Me.panel3)
            Me.panel1.Controls.Add(Me.panel2)
            Me.Controls.Add(Me.panel1)
        End Sub
    
        Private Sub HandleDraggableControlMouseDown(sender As Object, e As MouseEventArgs) Handles panel1.MouseDown, panel2.MouseDown, panel3.MouseDown
            Dim target As Control = TryCast(sender, Control)
            If (Not target Is Nothing) Then
                Dim pt As Point = Me.PointToClient(target.PointToScreen(Point.Empty))
                target.Parent = Me
                target.BringToFront()
                target.Location = pt
                Me.isMouseDown = True
                Me.cachedControlPos = pt
                Me.cachedMousePos = Control.MousePosition
            End If
        End Sub
    
        Private Sub HandleDraggableControlMouseMove(sender As Object, e As MouseEventArgs) Handles panel1.MouseMove, panel2.MouseMove, panel3.MouseMove
            If (Me.isMouseDown) Then
                Dim target As Control = TryCast(sender, Control)
                If (Not target Is Nothing) Then
                    Dim x As Integer = (Me.cachedControlPos.X + (Control.MousePosition.X - Me.cachedMousePos.X))
                    Dim y As Integer = (Me.cachedControlPos.Y + (Control.MousePosition.Y - Me.cachedMousePos.Y))
                    target.Location = New Point(x, y)
    
                    'c2 = (c1 + (m2 - m1))
    
                End If
            End If
        End Sub
    
        Private Sub HandleDraggableControlMouseUp(sender As Object, e As MouseEventArgs) Handles panel1.MouseUp, panel2.MouseUp, panel3.MouseUp
            Me.cachedControlPos = Point.Empty
            Me.cachedMousePos = Point.Empty
            Me.isMouseDown = False
        End Sub
    
        Private cachedMousePos As Point
        Private cachedControlPos As Point
        Private isMouseDown As Boolean
    
        Private WithEvents panel1 As Panel
        Private WithEvents panel2 As Panel
        Private WithEvents panel3 As Panel
    
    End Class
    

    更新 1

    在更改父级并将其移到前面后设置新位置很重要。

    target.Parent = Me
    target.BringToFront()
    target.Location = pt '<---
    

    更新 2

    所以我已将其范围缩小到导致此问题的原因,结果是Selectable control style。您可以通过子类化按钮类并删除构造函数中的样式来验证这一点。

    Public Class UIButton
        Inherits Button
    
        Public Sub New()
            MyBase.SetStyle(ControlStyles.Selectable, False)
        End Sub
    
    End Class
    

    那么我们该如何解决这个问题呢?好吧,AFAIK 没有简单的解决方案。可以预料,可选择的控件将以不同于那些不能的方式处理鼠标消息的方式。我能想到的唯一方法(它可能是一种肮脏的方法)是将控件子类化并拦截鼠标消息。以下代码不是最终解决方案,因此请谨慎使用。

    Public Class UIButton
        Inherits Button
    
        Protected Overrides Sub WndProc(ByRef m As Message)
            Select Case m.Msg
                Case WM.LBUTTONDOWN
                    Dim dw As New DWORD With {.value = m.LParam}
                    Dim vk As Integer = m.WParam.ToInt32()
                    MyBase.OnMouseDown(New MouseEventArgs(Windows.Forms.MouseButtons.Left, 0, dw.loword, dw.hiword, 0))
                    Debug.WriteLine("X={0}, Y={1}", dw.loword, dw.hiword)
                    Exit Select
                Case WM.MOVE
                    Dim dw As New DWORD With {.value = m.LParam}
                    Dim vk As Integer = m.WParam.ToInt32()
                    If (vk = Keys.LButton) Then
                        MyBase.OnMouseMove(New MouseEventArgs(Windows.Forms.MouseButtons.Left, 0, dw.loword, dw.hiword, 0))
                        Debug.WriteLine("X={0}, Y={1}", dw.loword, dw.hiword)
                    End If
                    Exit Select
                Case WM.LBUTTONUP
                    Dim dw As New DWORD With {.value = m.LParam}
                    Dim vk As Integer = m.WParam.ToInt32()
                    MyBase.OnMouseUp(New MouseEventArgs(Windows.Forms.MouseButtons.Left, 0, dw.loword, dw.hiword, 0))
                    Debug.WriteLine("X={0}, Y={1}", dw.loword, dw.hiword)
                    Exit Select
            End Select
            MyBase.WndProc(m)
        End Sub
    
        Private Enum WM As Integer
            MOVE = &H200
            LBUTTONDOWN = &H201
            LBUTTONUP = &H202
        End Enum
    
        <StructLayout(LayoutKind.Explicit)> _
        Private Structure DWORD
            <FieldOffset(0)> Public value As Integer
            <FieldOffset(0)> Public loword As Short
            <FieldOffset(2)> Public hiword As Short
        End Structure
    
    End Class
    

    【讨论】:

    • 感谢您的回复。我想拖动面板内的控件,而面板位于表格布局面板内,所以首先我删除了控件表单面板并在表单中添加控件,然后我拖动按钮控件使其无法清楚地拖动问题。 (这意味着快速拖动它不能正常工作)
    • 您能否更新您的问题,用一个突出问题的示例表格?我无法重现当前代码带来的不便。顺便说一句,您的命名约定有点奇怪。例如,如果方法名为Button_MouseDown,您是否真的希望发送者是KryptonGroupPanel?此外,您的代码充满了后期绑定。你应该把选项严格on
    • 谢谢。但这也是我快速移动光标光标离开控件
    • 这样检查。添加表格布局面板停靠栏填写表格。在面板侧面的添加按钮之后,在表格布局面板停靠栏填充中添加面板现在检查它。快速移动光标光标离开控件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-11
    • 2011-10-11
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    相关资源
    最近更新 更多