C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[5]: DragDropのキャンセルについて


(過去ログ 115 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■67723 / inTopicNo.1)  DragDropのキャンセルについて
  
□投稿者/ Poaw (3回)-(2013/08/27(Tue) 14:53:07)

分類:[.NET 全般] 

お世話になります。

VB2008でDragDropを使用しています。
実際には、図形とかテキストとかを移動とかコピーとかするのではないです。
Panel内に1000個のLabelを配置してそれぞれのTEXTに通し番号を与えます。
任意の番号で何番から何番までと範囲を指定するのにDragDropを使用したいのです。

現在実現できていないのは、範囲指定中に他のPanelやControlなどにDragEnterした場合に
DragDrop状態をやめたいのですが、やめる方法がわかりません。

QueryContinueDragでの
e.Action = DragAction.Cancel
は、マウスやKBのアクションが無いので使用できません。

よろしくお願いいたします。
引用返信 編集キー/
■67725 / inTopicNo.2)  Re[1]: DragDropのキャンセルについて
□投稿者/ shu (371回)-(2013/08/27(Tue) 17:45:20)
No67723 (Poaw さん) に返信

> 現在実現できていないのは、範囲指定中に他のPanelやControlなどにDragEnterした場合に
> DragDrop状態をやめたいのですが、やめる方法がわかりません。
DragEnterでドロップ受入検査をして
DragDropでドロップ受入検査後、アクションを起こすようにすれば
とくにキャンセルを考える必要がない気がしますが、どのような実装をされているのでしょう?
引用返信 編集キー/
■67733 / inTopicNo.3)  Re[2]: DragDropのキャンセルについて
□投稿者/ Poaw (5回)-(2013/08/28(Wed) 11:13:08)
No67725 (shu さん) に返信
> ■No67723 (Poaw さん) に返信
>
>>現在実現できていないのは、範囲指定中に他のPanelやControlなどにDragEnterした場合に
>>DragDrop状態をやめたいのですが、やめる方法がわかりません。
> DragEnterでドロップ受入検査をして
> DragDropでドロップ受入検査後、アクションを起こすようにすれば
> とくにキャンセルを考える必要がない気がしますが、どのような実装をされているのでしょう?

早速のご回答ありがとうございます。

キャンセルができるとコーディング的に簡単なのですが、それ以外の方法を考えてみます。

動作概要としまして
パネル内の1000個の任意のラベル(例えば番号=5)のMouseDownでDoDragDropをして他のラベル(例えば番号=14)のDragEnterで指定されたラベルの
範囲(5〜14)BackColorを選択色にしてゆきます。マウスの移動で範囲が変わります。任意のラベルでDropすると範囲が確定します。
そこで、他のパネルやコントロールにDragEnterした場合にこの選択色にした範囲を元のBackColorに戻しています(選択の中止)。
しかし、他のコントロールではDragDropをしていないため再び1000個のラベルに戻るとマウスカーソルとDrag状態が範囲選択中のままです。
これに困っています。

ご理解いただけたでしょうか。


引用返信 編集キー/
■67736 / inTopicNo.4)  Re[3]: DragDropのキャンセルについて
□投稿者/ shu (372回)-(2013/08/28(Wed) 14:05:07)
No67733 (Poaw さん) に返信
> ■No67725 (shu さん) に返信
>
> 早速のご回答ありがとうございます。
>
> キャンセルができるとコーディング的に簡単なのですが、それ以外の方法を考えてみます。
>
> 動作概要としまして
> パネル内の1000個の任意のラベル(例えば番号=5)のMouseDownでDoDragDropをして他のラベル(例えば番号=14)のDragEnterで指定されたラベルの
> 範囲(5〜14)BackColorを選択色にしてゆきます。マウスの移動で範囲が変わります。任意のラベルでDropすると範囲が確定します。
> そこで、他のパネルやコントロールにDragEnterした場合にこの選択色にした範囲を元のBackColorに戻しています(選択の中止)。
> しかし、他のコントロールではDragDropをしていないため再び1000個のラベルに戻るとマウスカーソルとDrag状態が範囲選択中のままです。
> これに困っています。
>
DragDrop前に取り消される可能性がある処理が動くという実装に無理があるように思います。

MouseDown => MouseMove => MouseUp
で処理するのが無難だと思います。

引用返信 編集キー/
■67737 / inTopicNo.5)  Re[3]: DragDropのキャンセルについて
□投稿者/ 魔界の仮面弁士 (316回)-(2013/08/28(Wed) 20:00:02)
No67733 (Poaw さん) に返信
> キャンセルができるとコーディング的に簡単なのですが、それ以外の方法を考えてみます。

「ドロップされた側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Drag 系のイベントが使われますが、
「ドラッグされる側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Mouse 系のイベントを使った方が便利です。
引用返信 編集キー/
■67738 / inTopicNo.6)  Re[4]: DragDropのキャンセルについて
□投稿者/ 魔界の仮面弁士 (317回)-(2013/08/29(Thu) 10:23:30)
No67737 (魔界の仮面弁士) に追記
> 「ドロップされた側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Drag  系のイベントが使われますが、
> 「ドラッグされる側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Mouse 系のイベントを使った方が便利です。

作ってみました。こういうイメージで良いのかな。


Public Class Form1

#Region "コントロールの配置処理"
    Private panel1 As New FlowLayoutPanel() With {.AutoScroll = True, .Dock = DockStyle.Fill}
    Private labels As New List(Of Label)() With {.Capacity = 1000}
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
        '1000 個のラベルを載せたパネルを生成
        Controls.Add(panel1)
        For l As Integer = 0 To 999
            Dim lbl As New Label()
            lbl.AutoSize = True
            lbl.BorderStyle = BorderStyle.Fixed3D
            lbl.Text = l.ToString("000")
            AddHandler lbl.MouseUp, AddressOf labels_MouseUp
            AddHandler lbl.MouseDown, AddressOf labels_MouseDown
            AddHandler lbl.MouseMove, AddressOf labels_MouseMove
            labels.Add(lbl)
        Next
        panel1.Controls.AddRange(labels.ToArray())

        'AutoScroll の領域を再計算させるためのおまじない
        Me.Width += 32
        Me.Width -= 32
    End Sub
#End Region

#Region "ドラッグ & ドロップ処理"
    'ドラッグの開始元/終了先の番号(0〜999)。-1 なら領域外。
    Private labelFrom As Integer = -1
    Private labelTo As Integer = -1

    Private Sub labels_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs)
        If e.Button = MouseButtons.Left Then
            labelFrom = labels.FindIndex(Function(lbl) lbl Is sender)
            AddHandler Application.Idle, AddressOf AppIdle
        Else
            labelFrom = -1
        End If
        labelTo = labelFrom
    End Sub
    Private Sub labels_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs)
        If labelFrom >= 0 Then
            Dim pos As Point = panel1.PointToClient(Cursor.Position)
            labelTo = labels.FindIndex(Function(lbl) lbl.Bounds.Contains(pos))
        End If
    End Sub
    Private Sub labels_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs)
        If labelFrom >= 0 Then
            RemoveHandler Application.Idle, AddressOf AppIdle
            UpdateLabelColor()
            labelFrom = -1
            labelTo = -1
        End If
    End Sub
#End Region

#Region "ラベルの背景を着色"
    Private Sub UpdateLabelColor()
        For l As Integer = 0 To labels.Count - 1
            If labelTo >= 0 AndAlso l.Between(labelFrom, labelTo) Then
                labels(l).BackColor = Color.Gold
            Else
                labels(l).ResetBackColor()
            End If
        Next
    End Sub

    Private Sub AppIdle(ByVal sender As Object, ByVal e As EventArgs)
        UpdateLabelColor()
    End Sub
#End Region

End Class

#Region "ヘルパーメソッド"

Public Module Sample
    <System.Runtime.CompilerServices.Extension()> _
    Public Function Between(Of T As IComparable)(ByVal value As T, ByVal lower As T, ByVal higher As T) As Boolean
        If lower.CompareTo(higher) < 0 Then
            Return lower.CompareTo(value) <= 0 AndAlso value.CompareTo(higher) <= 0
        Else
            Return higher.CompareTo(value) <= 0 AndAlso value.CompareTo(lower) <= 0
        End If
    End Function
End Module

#End Region

引用返信 編集キー/
■67803 / inTopicNo.7)  Re[5]: DragDropのキャンセルについて
□投稿者/ Poaw (6回)-(2013/09/03(Tue) 11:49:55)
No67738 (魔界の仮面弁士 さん) に返信
> ■No67737 (魔界の仮面弁士) に追記
>>「ドロップされた側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Drag 系のイベントが使われますが、
>>「ドラッグされる側が、ドラッグ中またはドラッグ完了時にアクションを起こす」場合は Mouse 系のイベントを使った方が便利です。
>
> 作ってみました。こういうイメージで良いのかな。
>

魔界の仮面弁士 様
ご親切なご回答をありがとうございます。
参考にさせていただきます。
VB6ではMouseEnterが無かったのでDragDropを使用しましたが、Vb2008ではMouseイベントが増えました。
VB6からVB2008の移植を主に行っていましたので気がつきませんでした。
これで解決しそうです。

ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -