2014-06-30 152 views
1

在我的應用程序中,我想將控件移到另一側。在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 

我的問題是,如果快速拖動控件不移動光標控件只移動爲什麼?我的編碼有什麼問題?如何解決問題?

回答

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

所以我已經將範圍縮小到什麼造成這個問題,它原來是Selectablecontrol 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 
+0

感謝您的回覆。我想拖動面板內的控件,面板在桌面佈局面板內,所以首先我刪除控件窗體面板,然後在窗體中添加控件,然後拖動按鈕控件,使其不會明顯拖動。 (這意味着快速拖動它不能正常工作) – Sathish

+0

你能用突出顯示問題的示例表單更新你的問題嗎?我不能用現行的代碼重現不便之處。順便說一句,你的命名約定有點奇怪。例如,如果方法名爲'Button_MouseDown',你真的希望發件人是'KryptonGroupPanel'嗎?此外,你的代碼充滿了後期綁定。你應該選擇嚴格'開'。 –

+0

檢查我的問題 – Sathish