DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

Drag&Dropを行う

ここではドラッグ&ドロップの例として、あるリストボックス内のアイテムをもう一つのリストボックスにドラッグ&ドロップにより移動させる方法を紹介します。

ドラッグ&ドロップの基本

まずは、ドロップを受け入れるリストボックスのAllowDropプロパティをTrueにしておきます。

実際にドラッグを開始するには、ドラッグされるアイテムのあるリストボックスのDoDragDropメソッドを呼び出します。ドロップを受け入れるリストボックスでは、リストボックス内にドラッグされた時にDragEnterイベントが発生しますので、ここでドロップを受け入れるか、受け入れるとしたらどのように受け入れるか(コピーか移動か等)を決定します。リストボックスにドロップされるとDragDropイベントが発生しますので、ここでドロップされたデータを取得し、リストボックスへデータを追加します。

次のコードでは、フォーム(Form1)にリストボックスが2つあり(ListBox1,ListBox2)、ListBox1のアイテムをドラッグ&ドロップによりListBox2に移動できるようにしています。

VB.NET
コードを隠すコードを選択
'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
        ByVal e As EventArgs) Handles MyBase.Load
    'ひとつのアイテムしか選択できないようにする
    ListBox1.SelectionMode = SelectionMode.One
    ListBox2.SelectionMode = SelectionMode.One

    'ListBox1にアイテムを追加
    Dim i As Integer
    For i = 0 To 4
        ListBox1.Items.Add(i.ToString())
    Next i
    'ListBox2にアイテムを追加
    For i = 5 To 9
        ListBox2.Items.Add(i.ToString())
    Next i

    'ListBox2へのドロップを受け入れる
    ListBox2.AllowDrop = True

    'ListBox1のイベントハンドラを追加
    AddHandler ListBox1.MouseDown, AddressOf ListBox1_MouseDown
    'ListBox2のイベントハンドラを追加
    AddHandler ListBox2.DragEnter, AddressOf ListBox2_DragEnter
    AddHandler ListBox2.DragDrop, AddressOf ListBox2_DragDrop
End Sub

'ListBox1でマウスボタンが押された時
Private Sub ListBox1_MouseDown( _
        ByVal sender As Object, ByVal e As MouseEventArgs)
    'マウスの左ボタンだけが押されている時のみドラッグできるようにする
    If e.Button = MouseButtons.Left Then
        'ドラッグの準備
        Dim lbx As ListBox = CType(sender, ListBox)
        'ドラッグするアイテムのインデックスを取得する
        Dim itemIndex As Integer = lbx.IndexFromPoint(e.X, e.Y)
        If itemIndex < 0 Then
            Return
        End If 'ドラッグするアイテムの内容を取得する
        Dim itemText As String = CStr(lbx.Items(itemIndex))

        'ドラッグ&ドロップ処理を開始する
        Dim dde As DragDropEffects = _
            lbx.DoDragDrop(itemText, DragDropEffects.All)

        'ドロップ効果がMoveの時はもとのアイテムを削除する
        If dde = DragDropEffects.Move Then
            lbx.Items.RemoveAt(itemIndex)
        End If
    End If
End Sub

'ListBox2内にドラッグされた時
Private Sub ListBox2_DragEnter( _
        ByVal sender As Object, ByVal e As DragEventArgs)
    'ドラッグされているデータがstring型か調べ、
    'そうであればドロップ効果をMoveにする
    If e.Data.GetDataPresent(GetType(String)) Then
        e.Effect = DragDropEffects.Move
    Else
        'string型でなければ受け入れない
        e.Effect = DragDropEffects.None
    End If
End Sub

'ListBox2にドロップされたとき
Private Sub ListBox2_DragDrop( _
        ByVal sender As Object, ByVal e As DragEventArgs)
    'ドロップされたデータがstring型か調べる
    If e.Data.GetDataPresent(GetType(String)) Then
        Dim target As ListBox = CType(sender, ListBox)
        'ドロップされたデータ(string型)を取得
        Dim itemText As String = _
            CStr(e.Data.GetData(GetType(String)))
        'ドロップされたデータをリストボックスに追加する
        target.Items.Add(itemText)
    End If
End Sub
C#
コードを隠すコードを選択
//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //ひとつのアイテムしか選択できないようにする
    ListBox1.SelectionMode = SelectionMode.One;
    ListBox2.SelectionMode = SelectionMode.One;

    //ListBox1にアイテムを追加
    for (int i = 0; i < 5; i++)
        ListBox1.Items.Add(i.ToString());
    //ListBox2にアイテムを追加
    for (int i = 5; i < 10; i++)
        ListBox2.Items.Add(i.ToString());

    //ListBox2へのドロップを受け入れる
    ListBox2.AllowDrop = true;

    //ListBox1のイベントハンドラを追加
    ListBox1.MouseDown += new MouseEventHandler(ListBox1_MouseDown);
    //ListBox2のイベントハンドラを追加
    ListBox2.DragEnter += new DragEventHandler(ListBox2_DragEnter);
    ListBox2.DragDrop += new DragEventHandler(ListBox2_DragDrop);
}

//ListBox1でマウスボタンが押された時
private void ListBox1_MouseDown(object sender, MouseEventArgs e)
{
    //マウスの左ボタンだけが押されている時のみドラッグできるようにする
    if (e.Button == MouseButtons.Left)
    {
        //ドラッグの準備
        ListBox lbx = (ListBox) sender;
        //ドラッグするアイテムのインデックスを取得する
        int itemIndex = lbx.IndexFromPoint(e.X, e.Y);
        if (itemIndex < 0) return;
        //ドラッグするアイテムの内容を取得する
        string itemText = (string) lbx.Items[itemIndex];

        //ドラッグ&ドロップ処理を開始する
        DragDropEffects dde =
            lbx.DoDragDrop(itemText, DragDropEffects.All);

        //ドロップ効果がMoveの時はもとのアイテムを削除する
        if (dde == DragDropEffects.Move)
            lbx.Items.RemoveAt(itemIndex);
    }
}

//ListBox2内にドラッグされた時
private void ListBox2_DragEnter(object sender, DragEventArgs e)
{
    //ドラッグされているデータがstring型か調べ、
    //そうであればドロップ効果をMoveにする
    if (e.Data.GetDataPresent(typeof(string)))
        e.Effect = DragDropEffects.Move;
    else
        //string型でなければ受け入れない
        e.Effect = DragDropEffects.None;
}

//ListBox2にドロップされたとき
private void ListBox2_DragDrop(object sender, DragEventArgs e)
{
    //ドロップされたデータがstring型か調べる
    if (e.Data.GetDataPresent(typeof(string)))
    {
        ListBox target = (ListBox) sender;
        //ドロップされたデータ(string型)を取得
        string itemText = 
            (string) e.Data.GetData(typeof(string));
        //ドロップされたデータをリストボックスに追加する
        target.Items.Add(itemText);
    }
}

上記のコードではドラッグするデータとしてString型を使用しました。しかし、別プロセスのアプリケーションにドロップするのでなければ、どのような型のデータであってもかまいません。(別プロセスのアプリケーションにドロップする場合は、Control.DoDragDrop メソッドによると、「基本マネージ クラス (String 、 Bitmap 、または Metafile)、あるいは ISerializable または IDataObject を実装するオブジェクトのいずれかである必要があります」とのことです。)

より完全な方法

上記のコードではドラッグ&ドロップ処理に必要な最低限のことしか行っていません。これを改良し、もう少しまともなコードにしていきましょう。

まず、MouseDownイベントですぐにドラッグ処理を開始するのは問題です。これでは、その後発生するはずのClickイベントが発生しません。本来ならばマウスボタンが押され、マウスがある距離以上動いたところではじめてドラッグされるべきです。この「距離」はSystemInformation.DragSizeプロパティで取得可能ですので、これを使ってMouseMoveイベントハンドラでドラッグを開始すべきか調べればよい訳です。

また、Ctrlキーを押しながらのドラッグでドロップ効果をCopyにしたいものです。そのためには、ListBox2のDragEnterイベントハンドラでe.KeyStateによりCtrlキーが押されているか調べ、押されていればe.EffectをDragDropEffects.Copyにします。

しかし、DragEnterイベントハンドラでドロップ効果の指定を行うと、ListBox2内にドラッグされてからCtrlキーを押してもドロップ効果は変化しません。このようなことのないように、ドロップ効果の指定をDragOverイベントハンドラで行うように変更します。(下のコードではさらに、Altキーを押しながらのドラッグで、ドロップ効果がLinkになるようにしています。そのため、DoDragDropメソッドでドラッグを開始する時、DragDropEffects.Allに加えてDragDropEffects.Linkも指定しています。)

さらに、ドラッグ中にマウスの右ボタンを押すことにより、ドラッグがキャンセルできるようにしましょう。ドラッグのキャンセルは、QueryContinueDragイベントハンドラで行います。e.KeyStateでマウスの右ボタンが押されているか調べ、押されていればe.ActionにDragAction.Cancelを指定して、ドラッグ操作をキャンセルします。(Escキーによるキャンセルはデフォルトで行われます。)

ついでに、ドラッグ中のマウスカーソルの形状も自分で用意したものに変更してみましょう。ドラッグ中のマウスカーソルの変更は、GiveFeedbackイベントハンドラで行います。e.UseDefaultCursorsをFalseにし、Cursor.Currentにカーソルを指定します。(下の例では、マウスポインタがListBox1やフォームにあるときには、ここで指定したカーソルになっていないかもしれません。これは、ListBox1やフォームのAllowDropプロパティがFalseになっているためです。この点を考慮すると、"noneCursor"は使わずに、e.UseDefaultCursorsをTrueにして既定のカーソルにしたほうが良いかもしれません。)

以上の機能を付け加えて書き直したコードが下記のコードです。なおここでは4つのカーソルファイル"none.cur"、"move.cur"、"copy.cur"、"link.cur"がアプリケーションと同じフォルダに存在しているものとします。"none.cur"はドロップできないときのカーソルで、"move.cur"はドロップ効果がMoveのとき、"copy.cur"はCopyのとき、"link.cur"はLinkのときのカーソルです。

VB.NET
コードを隠すコードを選択
'マウスの押された位置
Private mouseDownPoint As Point = Point.Empty
'アイコン
Private noneCursor As New Cursor("none.cur")
Private moveCursor As New Cursor("move.cur")
Private copyCursor As New Cursor("copy.cur")
Private linkCursor As New Cursor("link.cur")

'フォームのLoadイベントハンドラ
Private Sub Form1_Load(ByVal sender As Object, _
        ByVal e As EventArgs) Handles MyBase.Load
    'ひとつのアイテムしか選択できないようにする
    ListBox1.SelectionMode = SelectionMode.One
    ListBox2.SelectionMode = SelectionMode.One

    'ListBox1にアイテムを追加
    Dim i As Integer
    For i = 0 To 4
        ListBox1.Items.Add(i.ToString())
    Next i
    'ListBox2にアイテムを追加
    For i = 5 To 9
        ListBox2.Items.Add(i.ToString())
    Next i
    'ListBox2へのドロップを受け入れる
    ListBox2.AllowDrop = True

    'ListBox1のイベントハンドラを追加
    AddHandler ListBox1.MouseDown, AddressOf ListBox1_MouseDown
    AddHandler ListBox1.MouseMove, AddressOf ListBox1_MouseMove
    AddHandler ListBox1.MouseUp, AddressOf ListBox1_MouseUp
    AddHandler ListBox1.QueryContinueDrag, AddressOf ListBox1_QueryContinueDrag
    AddHandler ListBox1.GiveFeedback, AddressOf ListBox1_GiveFeedback
    'ListBox2のイベントハンドラを追加
    AddHandler ListBox2.DragOver, AddressOf ListBox2_DragOver
    AddHandler ListBox2.DragDrop, AddressOf ListBox2_DragDrop
End Sub

'ListBox1でマウスボタンが押された時
Private Sub ListBox1_MouseDown( _
        ByVal sender As Object, ByVal e As MouseEventArgs)
    'マウスの左ボタンだけが押されている時のみドラッグできるようにする
    If e.Button = MouseButtons.Left Then
        'ドラッグの準備
        Dim lbx As ListBox = CType(sender, ListBox)
        'マウスの押された位置を記憶
        If lbx.IndexFromPoint(e.X, e.Y) >= 0 Then
            mouseDownPoint = New Point(e.X, e.Y)
        End If
    Else
        mouseDownPoint = Point.Empty
    End If
End Sub

Private Sub ListBox1_MouseUp( _
    ByVal sender As Object, ByVal e As MouseEventArgs)
    mouseDownPoint = Point.Empty
End Sub

Private Sub ListBox1_MouseMove( _
        ByVal sender As Object, ByVal e As MouseEventArgs)
    If mouseDownPoint.IsEmpty = False Then
        'ドラッグとしないマウスの移動範囲を取得する
        Dim moveRect As New Rectangle( _
            mouseDownPoint.X - SystemInformation.DragSize.Width / 2, _
            mouseDownPoint.Y - SystemInformation.DragSize.Height / 2, _
            SystemInformation.DragSize.Width, _
            SystemInformation.DragSize.Height)
        'ドラッグとする移動範囲を超えたか調べる
        If Not moveRect.Contains(e.X, e.Y) Then
            'ドラッグの準備
            Dim lbx As ListBox = CType(sender, ListBox)
            'ドラッグするアイテムのインデックスを取得する
            Dim itemIndex As Integer = _
                lbx.IndexFromPoint(mouseDownPoint)
            If itemIndex < 0 Then
                Return
            End If 'ドラッグするアイテムの内容を取得する
            Dim itemText As String = CStr(lbx.Items(itemIndex))

            'ドラッグ&ドロップ処理を開始する
            Dim dde As DragDropEffects = _
                lbx.DoDragDrop(itemText, _
                    DragDropEffects.All Or DragDropEffects.Link)

            'ドロップ効果がMoveの時はもとのアイテムを削除する
            If dde = DragDropEffects.Move Then
                lbx.Items.RemoveAt(itemIndex)
            End If
            mouseDownPoint = Point.Empty
        End If
    End If
End Sub

'マウスポインタを指定する
Private Sub ListBox1_GiveFeedback( _
        ByVal sender As Object, ByVal e As GiveFeedbackEventArgs)
    '既定のカーソルを使用しない
    e.UseDefaultCursors = False
    'ドロップ効果にあわせてカーソルを指定する
    If (e.Effect And DragDropEffects.Move) = _
            DragDropEffects.Move Then
        Cursor.Current = moveCursor
    Else If (e.Effect And DragDropEffects.Copy) = _
                DragDropEffects.Copy Then
        Cursor.Current = copyCursor
    Else If (e.Effect And DragDropEffects.Link) = _
                DragDropEffects.Link Then
        Cursor.Current = linkCursor
    Else
        Cursor.Current = noneCursor
    End If
End Sub

'ドラッグをキャンセルする
Private Sub ListBox1_QueryContinueDrag( _
        ByVal sender As Object, _
        ByVal e As QueryContinueDragEventArgs)
    'マウスの右ボタンが押されていればドラッグをキャンセル
    '"2"はマウスの右ボタンを表す
    If (e.KeyState And 2) = 2 Then
        e.Action = DragAction.Cancel
    End If
End Sub

Private Sub ListBox2_DragOver( _
        ByVal sender As Object, ByVal e As DragEventArgs)
    'ドラッグされているデータがstring型か調べる
    If e.Data.GetDataPresent(GetType(String)) Then
        If (e.KeyState And 8) = 8 And _
            (e.AllowedEffect And DragDropEffects.Copy) = _
            DragDropEffects.Copy Then
            'Ctrlキーが押されていればCopy
            '"8"はCtrlキーを表す
            e.Effect = DragDropEffects.Copy
        ElseIf (e.KeyState And 32) = 32 And _
            (e.AllowedEffect And DragDropEffects.Link) = _
            DragDropEffects.Link Then
            'Altキーが押されていればLink
            '"32"はAltキーを表す
            e.Effect = DragDropEffects.Link
        ElseIf (e.AllowedEffect And DragDropEffects.Move) = _
            DragDropEffects.Move Then
            '何も押されていなければMove
            e.Effect = DragDropEffects.Move
        Else
            e.Effect = DragDropEffects.None
        End If
    Else
        'string型でなければ受け入れない
        e.Effect = DragDropEffects.None
    End If
End Sub

'ListBox2にドロップされたとき
Private Sub ListBox2_DragDrop( _
        ByVal sender As Object, ByVal e As DragEventArgs)
    'ドロップされたデータがstring型か調べる
    If e.Data.GetDataPresent(GetType(String)) Then
        Dim target As ListBox = CType(sender, ListBox)
        'ドロップされたデータ(string型)を取得
        Dim itemText As String = CStr(e.Data.GetData(GetType(String)))
        If (e.Effect And DragDropEffects.Link) = _
                DragDropEffects.Link Then
            itemText = "[Link]" + itemText
        End If
        'ドロップされたデータをリストボックスに追加する
        target.Items.Add(itemText)
    End If
End Sub
C#
コードを隠すコードを選択
//マウスの押された位置
private Point mouseDownPoint = Point.Empty;
//アイコン
private Cursor noneCursor = new Cursor("none.cur");
private Cursor moveCursor = new Cursor("move.cur");
private Cursor copyCursor = new Cursor("copy.cur");
private Cursor linkCursor = new Cursor("link.cur");

//フォームのLoadイベントハンドラ
private void Form1_Load(object sender, System.EventArgs e)
{
    //ひとつのアイテムしか選択できないようにする
    ListBox1.SelectionMode = SelectionMode.One;
    ListBox2.SelectionMode = SelectionMode.One;

    //ListBox1にアイテムを追加
    for (int i = 0; i < 5; i++)
        ListBox1.Items.Add(i.ToString());
    //ListBox2にアイテムを追加
    for (int i = 5; i < 10; i++)
        ListBox2.Items.Add(i.ToString());

    //ListBox2へのドロップを受け入れる
    ListBox2.AllowDrop = true;

    //ListBox1のイベントハンドラを追加
    ListBox1.MouseDown += new MouseEventHandler(ListBox1_MouseDown);
    ListBox1.MouseMove += new MouseEventHandler(ListBox1_MouseMove);
    ListBox1.MouseUp += new MouseEventHandler(ListBox1_MouseUp);
    ListBox1.QueryContinueDrag +=
        new QueryContinueDragEventHandler(ListBox1_QueryContinueDrag);
    ListBox1.GiveFeedback += new GiveFeedbackEventHandler(ListBox1_GiveFeedback);
    //ListBox2のイベントハンドラを追加
    ListBox2.DragOver += new DragEventHandler(ListBox2_DragOver);
    ListBox2.DragDrop += new DragEventHandler(ListBox2_DragDrop);
}

//ListBox1でマウスボタンが押された時
private void ListBox1_MouseDown(object sender, MouseEventArgs e)
{
    //マウスの左ボタンだけが押されている時のみドラッグできるようにする
    if (e.Button == MouseButtons.Left)
    {
        //ドラッグの準備
        ListBox lbx = (ListBox) sender;
        //マウスの押された位置を記憶
        if (lbx.IndexFromPoint(e.X, e.Y) >= 0)
            mouseDownPoint = new Point(e.X, e.Y);
    }
    else
        mouseDownPoint = Point.Empty;
}

private void ListBox1_MouseUp(object sender, MouseEventArgs e)
{
    mouseDownPoint = Point.Empty;
}

private void ListBox1_MouseMove(object sender, MouseEventArgs e)
{
    if (mouseDownPoint != Point.Empty)
    {
        //ドラッグとしないマウスの移動範囲を取得する
        Rectangle moveRect = new Rectangle(
            mouseDownPoint.X - SystemInformation.DragSize.Width / 2,
            mouseDownPoint.Y - SystemInformation.DragSize.Height / 2,
            SystemInformation.DragSize.Width,
            SystemInformation.DragSize.Height);
        //ドラッグとする移動範囲を超えたか調べる
        if (!moveRect.Contains(e.X, e.Y))
        {
            //ドラッグの準備
            ListBox lbx = (ListBox) sender;
            //ドラッグするアイテムのインデックスを取得する
            int itemIndex = lbx.IndexFromPoint(mouseDownPoint);
            if (itemIndex < 0) return;
            //ドラッグするアイテムの内容を取得する
            string itemText = (string) lbx.Items[itemIndex];

            //ドラッグ&ドロップ処理を開始する
            DragDropEffects dde =
                lbx.DoDragDrop(itemText, 
                    DragDropEffects.All | DragDropEffects.Link);

            //ドロップ効果がMoveの時はもとのアイテムを削除する
            if (dde == DragDropEffects.Move)
                lbx.Items.RemoveAt(itemIndex);

            mouseDownPoint = Point.Empty;
        }
    }
}

//マウスポインタを指定する
private void ListBox1_GiveFeedback(
    object sender, GiveFeedbackEventArgs e)
{
    //既定のカーソルを使用しない
    e.UseDefaultCursors = false;
    //ドロップ効果にあわせてカーソルを指定する
    if ((e.Effect & DragDropEffects.Move) == 
            DragDropEffects.Move)
        Cursor.Current = moveCursor;
    else if ((e.Effect & DragDropEffects.Copy) == 
            DragDropEffects.Copy)
        Cursor.Current = copyCursor;
    else if ((e.Effect & DragDropEffects.Link) ==
            DragDropEffects.Link)
        Cursor.Current = linkCursor;
    else
        Cursor.Current = noneCursor;
}

//ドラッグをキャンセルする
private void ListBox1_QueryContinueDrag(
    object sender, QueryContinueDragEventArgs e)
{
    //マウスの右ボタンが押されていればドラッグをキャンセル
    //"2"はマウスの右ボタンを表す
    if ((e.KeyState & 2) == 2)
        e.Action = DragAction.Cancel;
}

private void ListBox2_DragOver(object sender, DragEventArgs e)
{
    //ドラッグされているデータがstring型か調べる
    if (e.Data.GetDataPresent(typeof(string)))
    {
        //Ctrlキーが押されていればCopy
        //"8"はCtrlキーを表す
        if ((e.KeyState & 8) == 8 &&
            (e.AllowedEffect & DragDropEffects.Copy) == 
                DragDropEffects.Copy)
            e.Effect = DragDropEffects.Copy;
        //Altキーが押されていればLink
        //"32"はAltキーを表す
        else if ((e.KeyState & 32) == 32 &&
            (e.AllowedEffect & DragDropEffects.Link) ==
                DragDropEffects.Link)
            e.Effect = DragDropEffects.Link;
        //何も押されていなければMove
        else if ((e.AllowedEffect & DragDropEffects.Move) ==
                DragDropEffects.Move)
            e.Effect = DragDropEffects.Move;
        else
            e.Effect = DragDropEffects.None;
    }
    else
        //string型でなければ受け入れない
        e.Effect = DragDropEffects.None;
}

//ListBox2にドロップされたとき
private void ListBox2_DragDrop(object sender, DragEventArgs e)
{
    //ドロップされたデータがstring型か調べる
    if (e.Data.GetDataPresent(typeof(string)))
    {
        ListBox target = (ListBox) sender;
        //ドロップされたデータ(string型)を取得
        string itemText = 
            (string) e.Data.GetData(typeof(string));
        if ((e.Effect & 
                DragDropEffects.Link) == DragDropEffects.Link)
            itemText = "[Link]" + itemText;
        //ドロップされたデータをリストボックスに追加する
        target.Items.Add(itemText);
    }
}
補足:

さて、上記のコード(あるいはControl.DoDragDrop メソッド)をご覧になった方は、このコードを複数のアイテムが選択されたリストボックスに応用したいと考えるかもしれません。ところがこれがなかなか大変なのです(.NET Framework 1.1現在)。というのは、実際にやってみると分かりますが、なぜかリストボックスのSelectedIndices、SelectedItemsプロパティなどが正常に取得できないのです。リストボックス間のドラッグ&ドロップのサンプルコードは多く見ますが、そのどれもが複数のアイテムのドラッグ&ドロップに対応していないのはこのためです。(少なくとも私はそのようなサンプルを見たことがありませんし、それどころか、このことに触れられてもいません。)

この問題の解決法に関しては、ニュースグループ「microsoft.public.dotnet.languages.csharp」の「RE: ListBox.SelectedItems and DragDrop(From:Lion Shi)」(リンク切れ)の投稿が参考になります。

これによると解決法は、フォームのActivatedイベントハンドラで一回だけ
VB.NET
コードを隠すコードを選択
ListBox1.Focus()
SendKeys.Send("{LEFT}")
C#
コードを隠すコードを選択
ListBox1.Focus();
SendKeys.Send("{LEFT}");
を行うとのことです。私がやってみたところではこれだけではダメで、DoDragDropメソッド終了後ごとに同じことをしなければいけないようです。

しかしこれが解決になっているのか疑問です。ListBoxの使用はあきらめて、ListViewを使った方が良いかもしれません。
  • 履歴:
  • 2009/9/20 カーソルに関する説明を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。