您需要將當前鼠標的位置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
感謝您的回覆。我想拖動面板內的控件,面板在桌面佈局面板內,所以首先我刪除控件窗體面板,然後在窗體中添加控件,然後拖動按鈕控件,使其不會明顯拖動。 (這意味着快速拖動它不能正常工作) – Sathish
你能用突出顯示問題的示例表單更新你的問題嗎?我不能用現行的代碼重現不便之處。順便說一句,你的命名約定有點奇怪。例如,如果方法名爲'Button_MouseDown',你真的希望發件人是'KryptonGroupPanel'嗎?此外,你的代碼充滿了後期綁定。你應該選擇嚴格'開'。 –
檢查我的問題 – Sathish