フレームワークでの動作を調べてみました。上のフレームワークではありません)。以外に対応する際に大きな障害となってしまいます。各フレームワークにおけるイベントの流れやコンセプトを参考としてまとめてみました。いう概念自体の理解を深める勉強の意味もあります。説明の中では具体的な例を使う方が分かりやすいので、図形描画アプリケーション「MyDraw」という仮想のアプリケーションを例に取ります。した場合は図形の「コピー」と扱われる操作仕様になっているとします。「Widget」を指していると解釈してください。一種のデータ通信です。マウスカーソルのドラッグという操作によってデータを送信側から受信側へと転送します。単純なデータ通信とは一風変わった手続きが必要になります。この記事でもそれを利用します。処理の開始を命令します。処理中にのみ発生する専用イベントが発生するようになります。通常のマウスイベントが発生する元通りの状態に戻ります。セッション」と呼びます。いう3つのイベントを受信して適切にフラグ管理等を行うことを思い付くかと思います。このアプローチは送信側ウィンドウと受信側ウィンドウが違うと実装が非常に難しくなると思われます。他人が作った別プログラムのウィンドウとD&Dで通信するとなれば絶望的です。最初からD&Dの機構を使うことを検討するべきでしょう。(この操作を誰がD&Dと呼ぶのかという問題もありますが)。本記事では、あくまでデータ通信としてのD&Dを扱います。機構は同じ考え方で利用できます。以下に送信側と受信側それぞれの典型的なD&D処理の流れを記します。送信側におけるD&D処理の流れ送信側の典型的なD&D処理の流れを次に記します。送信側で重要なポイントは3点あります。D&Dセッションは送信側が明示的に開始する1つ目のポイントは、送信側からD&Dの処理を明示的に開始する必要がある点です。いうわけではない、という意味で重要なポイントです。D&Dセッションを開始するときには「実施可能なアクション」を指定する点も重要です。一般的にD&Dで実行できる操作にはコピー、移動、リンクなどがあります。D&Dで転送するデータに対してどの操作を行えるかを受信側にかならず伝えます。「移動」できてしまうため、話がおかしくなります。送信側では基本的に何もしないで良いという点です。セッション中に発生するフィードバック用のイベントを受け取って送信側の処理を実行する必要があります。残念ながらフレームワークによって考え方のレベルで違っています。そのためフレームワークに依存しない一般的な手法を導き出すのは難しいかもしれません。セッション終了時に受信側から報告される実行結果に応じて後処理を実装する必要があることです。(さもなければ両方にデータが存在する、つまり「コピーした」状態になります)。メソッドの戻り値がD&Dの結果を表しています。そのため、D&Dの結果に対する送信側の後処理はセッション開始命令の直後に記す形になります。結果を知ることができません(そもそもGTK#の場合は非ブロッキング実行)。そのイベントハンドラでD&Dの結果に対する送信側後処理を実装します。受信側におけるD&D処理の流れ受信側の典型的なD&D処理の流れを次に記します。重要なポイントは3点です。「D&Dを受けられる」という宣言を行っておく必要がある点です。そのウィンドウの上にいくらD&D中のカーソルを持って行っても何も起こりません。この宣言はフレームワークによっては不要です。GTK#ではGtk.Drag.DestSetメソッドで宣言します。Cocoaでは特に何もせずともD&Dを受け付けることができます。D&D中のカーソル位置に応じてイベントを処理2つ目のポイントです。D&D中のカーソルが移動するごとにフレームワークからイベントが送信されます。ウィンドウ領域内で移動しているときのイベントです。「その時点でドロップしたらどのような処理が行われるか」をフレームワークに返答します。「ドロップ可能」かつ「ドロップしたら移動になる」と返答します。ドロップされたら処理を実行し、結果を返す3つ目のポイントです。それを伝える専用のイベントが受信側で発生します。受信側はそこで、どのような処理を実行したかを選んで返答します。仮にMyDrawでShiftを押しながら図形をドロップした場合を考えましょう。D&Dで転送された図形のデータをプログラム的に取得してキャンバスに配置します。フレームワークに対して「移動を実行した」とドロップ結果を返答します。受信側の処理は以上で終了となります。ここで、「受信側では送信側の図形データを削除していない」ことに注意してください。その中で送信側へ「受信側で移動が実行された」という情報を伝えます。D&Dセッションが完了すると図形が移動した状態になる、という仕組みになっています。「受信側でコピーが実行された」という情報が伝わるため、送信元の図形が削除されません。その結果、図形がコピーされた状態になります。各フレームワークでの実装サンプルWinFormsまず送信側についてです。WinFormsフレームワークでは、D&DセッションをControl.DoDragDropで開始します。試した限りどのControlオブジェクトのメソッドを呼び出しても違いが無いようです。(もちろんControl派生クラスのメソッド中で開始する場合)。そのデータに対してどのような操作を受信側に許可するかを指定します。このメソッドはD&Dセッションが完了するまで終了しません(ブロック実行)。DoDragDropメソッドの呼び出しに続けて記す形になります。続いて受信側についてです。関連のイベントが一切発生しません。そのためD&Dを受けたいUI要素では同プロパティをまずtrueに設定しておきます。各イベントに対する処理を普通に実装すれば問題ありません。「_DropToMeLabel」が配置されたウィンドウを持つウィンドウの実装コードを以下に記します。D&Dセッションを開始。}}WPFWPFのD&D関連処理は、ほとんどWinFormsの場合と同じです。WPFではD&DセッションをDragDrop.DoDragDropで開始します。D&Dで送信するデータ、そのデータに対してどのような操作を受信側に許可するかを指定します。このメソッドはD&Dセッションが完了するまで終了しません(ブロック実行)。DoDragDropメソッドの呼び出しに続けて記す形になります。続いて受信側についてです。関連のイベントが一切発生しません。そのためD&Dを受けたいUI要素では同プロパティをまずtrueに設定しておきます。各イベントに対する処理を普通に実装すれば問題ありません。サンプルとして、テキストデータとしてドラッグ可能なラベル「_DragMeLabel」と、テキストデータをドロップ可能なラベル「_DropToMeLabel」が配置されたウィンドウを持つウィンドウの実装コードを以下に記します。D&Dセッションを開始。}}GTK#GTK#では、GTKが元となっているので当然ですが、WinFormsやWPFとはD&Dの扱いも少し異なっています。私自身がGTKに詳しくないこともあり、GTK#の場合はあまり深く掘り下げていません。前もってフレームワークに宣言しておく必要があるようです。送信側ではGtk.WindowのAddEventメソッドを使ってマウスイベントを受信するように設定しておきます。D&Dセッション開始するにはGtk.Drag.Beginメソッドを使います。そのデータに対してどのような操作を受信側に許可するか等を指定します。その完了を待たずにすぐ終了します(ノンブロック実行)。セッション完了時に送信側で発生するDragDropイベント(成功時)またはDragFailedイベント(失敗時)に対する処理として実装します。続いて受信側についてです。メソッドで受信側のウィジェットをドロップ可能なウィジェットとしてフレームワークに宣言します。各イベントに対する処理を普通に実装すれば問題ありません。以下に簡単なサンプルを記します。X標準のGUIフレームワークの場合について記します。Cで普通に使う場合の話となります。.NETでもC#言語でもありませんのでご注意ください。Cをご存じない方へ補足すると、これはC#風に言えばメソッド名がdragImageで、第二引数以降にat、offset、event、pasteboard、source、そしてslideBackを受けるメソッドです)。このメソッドはD&Dセッションが完了するまで終了しません(ブロック実行)。メソッドの戻り値等では受信側が行った操作を知ることができません(私が試した限り...)。operation:で実装します。続いて受信側についてです。WinForms等とは異なり、受信側のviewをドロップ可能にするためにすることはありません。何も設定せずともdraggingEntered:、draggingExited:、draggingUpdated:、performDragOperation:の各メソッドが呼び出されるため、これらのメソッドに処理を普通に実装すれば問題ありません。サンプルとして、テキストデータとしてドラッグ可能で、テキストデータをドロップ可能なMyDraggableViewというviewの実装コードを以下に記します。Library.戻る。