同期されたRichTextBoxをドラッグ&ドロップにも対応させます。

ドラッグ&ドロップの場合、以下のような場合が考えられます。

ファイルがドロップされた
テキスト、リッチテキストがドロップされた
コントロール内部でドラッグ&ドロップがおこなわれた

この3つが考えられます。

まず「ファイルがドロップされた」場合について考えます。

DragEventArgs.Data.GetDataPresentでドロップされたものがファイルだった場合、OnDragDropFilesメソッドを呼び出して処理をさせています。複数個のファイルがドロップされても実際に処理がおこなわれるのはひとつだけです。

テキスト、リッチテキストがドロップされた
コントロール内部でドラッグ&ドロップがおこなわれた

このふたつですが、

とやってしまうと、外部からRtfデータがドロップされたのか、同一コントロール内部でのドラッグ&ドロップなのか区別できません。両者は別々の処理をするため区別する必要があります。

ドラッグが開始されるときにその情報をフィールド変数に記憶させておけばよいのですが、ドラッグが開始されるときをどうやって知ればいいのでしょうか?

DragEnterイベントを使えばいいじゃないか! DragEnterイベントはドラッグ中のイベントやテキストの選択範囲が、妥当なドロップターゲットに入ったときに発生するイベントですが、ドラッグが開始されたときにも発生します。

しかしこれは絶対ではありません。文字列を選択してゆっくりドラッグをするとDragEnterイベントは発生しますが、すばやくコントロールの外にドラッグしてしまうとこのイベントは発生しません。

ではどうするか? MouseLeaveイベントを使います。ただしMouseLeaveイベントはマウスポインタが要素の領域から離れた時に発生するイベントであり、ドラッグ開始以外のときも発生します。そこでマウスボタンが押されているかどうかを確認します。そうすればドラッグの開始を知ることができるのです。

ドラッグの開始を知ることができたらどのようなデータがドラッグされようとしているのか情報を保存してしまいましょう。

こんなクラスをつくります。

SyncRichTextBoxクラス内に静的フィールド変数

static DragDropRtfInfo _dragDropRtfInfo = null;

これでどのSyncRichTextBoxオブジェクトからでもどのようなデータがドラッグされているのかを知ることができます。

またドロップされたらそれを知る必要があります。このタイミングで_dragDropRtfInfo = null;とする必要があります。DragDropイベントを使えば自分のコントロールでドロップされたことを知ることができますが、ドラッグされたものが自分のコントロールでドロップされるかどうかはわかりません。それを知る方法、それは・・・

MouseMoveイベントです。

そこで

とやれば、うまくいきそうです。

さてOnDragDropInternal(DragEventArgs , DragDropRtfInfo)の内容ですが、次回に続きます。

同一コントロール内部のドラッグ&ドロップ 内容が同期されたRichTextBox(その9)