DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DragDropとコントロール移動を同時にしたんですが・・・

環境/言語:[WindowsVista VB.NET]
分類:[.NET]

2009/10/26(Mon) 16:18:14 編集(投稿者)
2009/10/26(Mon) 16:18:07 編集(投稿者)

はじめまして、VB.NET 2005のDragDropとコントロール移動について、質問させていただきます。

まず、エクスプローラーのDragDropのように、Dragするとアイコン(ここではbtn1)も同時に動くように↓

Private mousePoint As Point = Point.Empty
Dim dragBox As Rectangle = Rectangle.Empty
Dim Xsave As Integer, Ysave As Integer

Private Sub mouseDown_btn1(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btn1.MouseDown
Dim sz As Size = SystemInformation.DragSize
dragBox = New Rectangle(e.X - sz.Width / 2, e.Y - sz.Height / 2, sz.Width, sz.Height)
Xsave = e.X : Ysave = e.Y

If e.Button = MouseButtons.Left Then
mousePoint = New Point(e.X, e.Y)
End If
End Sub

Private Sub GiveFeedback_btn1(ByVal sender As System.Object, ByVal e As System.Windows.Forms.GiveFeedbackEventArgs) Handles btn1.GiveFeedback
If e.Effect = DragDropEffects.Move Then
btn1.Location = Point.op_Subtraction(Me.PointToClient(Cursor.Position), mousePoint)
End If
End Sub

Private Sub mouseMove_btn1(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btn1.MouseMove
If e.Button = Windows.Forms.MouseButtons.Left Then
If Not dragBox.Contains(e.X, e.Y) Then
Dim DropResult As DragDropEffects = btn1.DoDragDrop(sender, DragDropEffects.Move)
dragBox = Rectangle.Empty
End If
End If
End Sub

コントロール同士(btn1,btn2)が重なればFlatstyleを変更し、その状態でDropするとLocationを同じに↓


Private Sub dragEnter_btn2(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles btn2.DragEnter
btn2.flatstyle = FlatStyle.Popup
End Sub

Private Sub dragLeave_btn2(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn2.DragLeave
btn2.flatstyle = FlatStyle.Standard
End Sub

Private Sub dragOver_btn2(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles btn2.DragOver
If e.AllowedEffect = DragDropEffects.Move Then
e.Effect = DragDropEffects.Move
End If
End Sub

Private Sub dragDrop_btn2(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DragEventArgs) Handles btn2.DragDrop
If e.Effect = DragDropEffects.Move Then
Dim btn As Button = e.Data.GetData(GetType(Button))
If btn2.FlatStyle = FlatStyle.Popup Then
btn.Location = btn2.Location
btn2.flatstyle = FlatStyle.Standard
End If
Next
End If
End Sub

Private Sub mouseUp_btn1(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles btn1.MouseUp
mousePoint = Point.Empty
dragBox = Rectangle.Empty

If btn2.FlatStyle = FlatStyle.Popup Then
btn1.Location = btn2.Location
End If
Next
End Sub

と、上記のように記述して、btn1をbtn2に重ねたいのですが、btn2を前面に出さないとDragEnterが動作しません。
btn1を最前面に出した状態で、DragEnterを作動させる方法、何かあればよろしくお願いします。
お疲れ様です。
代替案ですが、ImageList_BeginDrag等を使って
ドラッグ中にButtonの画像を表示する方法があります。

' Button1とButton2を配置してください
Public Class Form2

    Dim ImageList1 As New ImageList

    Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
        Me._initialize()
        MyBase.OnLoad(e)
    End Sub

    Private Sub _initialize()
        Me.Button2.AllowDrop = True

        Dim bmp As New Bitmap(Me.Button1.Width, Me.Button1.Height)
        Me.Button1.DrawToBitmap(bmp, New Rectangle(0, 0, Me.Button1.Width, Me.Button1.Height))

        With Me.ImageList1
            .ImageSize = Me.Button1.Size
            .Images.Add(bmp)
        End With
    End Sub

    Private Sub Button1_MouseMove(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.MouseEventArgs) Handles Button1.MouseMove
        If e.Button = Windows.Forms.MouseButtons.Left Then
            WinAPI.ImageList_BeginDrag(Me.ImageList1.Handle, 0, 5, 5)
            WinAPI.ImageList_DragEnter(IntPtr.Zero, 5, 5)
            Me.Button1.DoDragDrop(Me.Button1, DragDropEffects.Copy)
            WinAPI.ImageList_DragLeave(IntPtr.Zero)
            WinAPI.ImageList_EndDrag()
        End If
    End Sub

    Private Sub Button1_QueryContinueDrag(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.QueryContinueDragEventArgs) Handles Button1.QueryContinueDrag
        Dim p As Point = Cursor.Position
        WinAPI.ImageList_DragMove(p.X, p.Y)
    End Sub

    Private Sub Button2_DragDrop(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DragEventArgs) Handles Button2.DragDrop
        Dim btn As Button = DirectCast(sender, Button)

        If e.Data.GetData(GetType(Button)) Is Me.Button1 Then
            Me.Button1.Location = btn.Location
            Me.Button1.BringToFront()
        End If
    End Sub

    Private Sub Button2_DragEnter(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.DragEventArgs) Handles Button2.DragEnter
        Dim btn As Button = DirectCast(sender, Button)

        If e.Data.GetData(GetType(Button)) Is Me.Button1 Then
            e.Effect = DragDropEffects.Copy
        End If
    End Sub

End Class
--------------------------------------------------------
Imports System.Runtime.InteropServices

' DragAndDrop中にボタンの画像を表示させるためのAPI群
Public Class WinAPI

    <DllImport("comctl32")> _
    Public Shared Function ImageList_BeginDrag(ByVal hdl As IntPtr, ByVal iTrack As Integer, _
        ByVal x As Integer, ByVal y As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        ' コードはなし
    End Function

    <DllImport("comctl32")> _
    Public Shared Function ImageList_DragEnter(ByVal hdl As IntPtr, ByVal x As Integer, _
        ByVal y As Integer) As <MarshalAs(UnmanagedType.Bool)> Boolean
        ' コードはなし
    End Function

    <DllImport("comctl32")> _
    Public Shared Function ImageList_DragMove(ByVal x As Integer, ByVal y As Integer) _
        As <MarshalAs(UnmanagedType.Bool)> Boolean
        ' コードはなし
    End Function

    <DllImport("comctl32")> _
    Public Shared Function ImageList_DragLeave(ByVal hdl As IntPtr) _
        As <MarshalAs(UnmanagedType.Bool)> Boolean
        ' コードはなし
    End Function

    <DllImport("comctl32")> _
    Public Shared Sub ImageList_EndDrag()
        ' コードはなし
    End Sub

End Class
丁寧な返答、ありがとうございます。
DragDropって、こんなにも種類があったんですね。
APIは今の私には少々難しいですが、形としては理想だったので、勉強しながら作成しようと思います。

それと、追記の質問で申し訳ないのですが、Drag中にマウスの下に出る破線の四角形や、他のコントロールに重ねた時に出る+は、なくしたり変更したりできるのでしょうか?
お疲れ様です。

すみませんが、私には即答できないので、
調べてみます。

どなたかフォローいただけると幸いです。
お疲れ様です。
返信が遅れましたが、ここにありました。

↓より完全な方法
http://dobon.net/vb/dotnet/control/draganddrop.html

(追加のコード)
    Private Sub Button1_GiveFeedback(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.GiveFeedbackEventArgs) Handles Button1.GiveFeedback
        e.UseDefaultCursors = False
        Cursor.Current = Cursors.Default
    End Sub

    Private Sub Button1_QueryContinueDrag(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.QueryContinueDragEventArgs) Handles Button1.QueryContinueDrag
        Cursor.Current = Cursors.Default
        ' 残りのコードは同じ
    End Sub
H.K.R.さん、返答ありがとうございます。
先月末から入院していて、返信が大幅に遅れてしまいました。
本当に申し訳ありません。

問題の方は、追加のコードでなんとかなりました。
丁寧な解説、ありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板