C#プログラミングTips

エクスプローラからのドラッグ&ドロップを受け付けるには

デジタルアドバンテージ
2001/03/30


 Windowsアプリケーションでファイルを開く場合、マウスを使ったドラッグ&ドロップは、最も直感的で便利な方法だ。しかしなぜか、.NET Frameworkのドキュメントを見ても、この方法が明記されていない。そこで今回は、エクスプローラで選択したファイルのドラッグ&ドロップをWindowsアプリケーションで受け取る方法をご紹介する。

 まずは、今回作成するサンプル・プログラムの全コードを示す。

 1: // dragdrop.cs
 2:
 3: using System;
 4: using System.Drawing;
 5: using System.WinForms;
 6:
 7: public class DragDrop : Form {
 8:     private ListBox listbox1;
 9:
10:     protected void listbox1_DragEnter(object s,DragEventArgs e){
11:         e.Effect = DragDropEffects.All;
12:     }
13:
14:     protected void listbox1_DragDrop(object s,DragEventArgs e) {
15:         if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
16:             foreach (string fileName
17:                         in (string[])e.Data.GetData(DataFormats.FileDrop)) {
18:                 listbox1.Items.Add(fileName);
19:             }
20:         }
21:     }
22:
23:     public DragDrop() {
24:         this.Size = new Size(340, 480);
25:         this.Text = "ドラッグ&ドロップ・サンプル";
26:
27:         this.listbox1       = new ListBox();
28:         listbox1.Dock       = DockStyle.Fill;
29:         listbox1.AllowDrop  = true;
30:         listbox1.DragEnter += new DragEventHandler(listbox1_DragEnter);
31:         listbox1.DragDrop  += new DragEventHandler(listbox1_DragDrop);
32:
33:         this.Controls.Add(listbox1);
34:     }
35:
36:     public static void Main() {
37:         Application.Run(new DragDrop());
38:     }
39: }
dragdrop.csのソースコード

 このプログラムを実行すると、以下の画面のように、クライアント領域いっぱいにリストボックスが貼り付けられたウィンドウが表示される。

今回作成したサンプル・プログラムを実行したところ
今回のサンプル・プログラムを起動すると、このようにウィンドウのクライント領域いっぱいにリストボックスが貼り付けられたウィンドウが表示される。

 この状態で、エクスプローラからいくつかのファイルをマウスで選択し、このウィンドウの上までドラッグすると、次の画面のように、このウィンドウがドラッグ&ドロップを受け付けることを示す十字マークがマウスのポインタに表示される。

エクスプローラでファイルを選択し、それらをマウスでドロップする
エクスプローラでファイルを選択して、それらをマウスで今回のウィンドウまでドラッグする。この場合マウス・ポインタには、直下にあるアプリケーションがドロップを受け付けることを示す「+マーク」が表示される。
  ドラッグ元のエクスプローラ。こちらでファイルを選択し、マウスでドラッグする。
  今回のアプリケーション。マウスでドラッグしている最中、マウス・ポインタのイメージに注目すると、それがドロップを受け付けることを示す「+マーク」が表示されていることが分かる。

 そしてマウスのボタンを離すと、次の画面のように選択していたすべてのファイルのフルパスがリストボックスに列挙される。このサンプル・プログラムの処理はここまでだが、こうしてファイルのフルパスさえ取得できれば、さまざまなアプリケーションで応用できるだろう。

ファイル・アイコンをドロップしたところ
エクスプローラからドラッグしたファイル・アイコンをサンプル・プログラム上でドロップしたところ。するとこのように、ドラッグしたファイルのフルパスがリストボックスに表示される。
  ドロップされたファイルのフルパスがこのように表示される。

ドラッグ&ドロップ処理では2つのイベント処理が必要

 それではドラッグ&ドロップを実装する手順を解説しよう。アプリケーションでドラッグ&ドロップを受け付けるには、2つのイベントに対応する必要がある。ファイルをドラッグした状態でマウスがウィンドウの領域に入ったときに発生するDragEnterイベントと、それに続いてマウスのボタンを離したときに発生するDragDropイベントの2つである。DragDropイベントが発生した時点でドラッグ&ドロップの操作は完了するので、このときにイベントとともに送られてくるデータ(選択されたファイル名が含まれているはず)を取得すればよい。

AllowDropプロパティの設定

 ところで、これら2つのイベントをどこで受け取ればよいだろうか? アプリケーションのウィンドウ全体にあたるフォームでも受け取り可能だが、これらのイベントはマウス・カーソルがある直下のコントロールにのみ送られる。今回はリストボックスをフォーム全体に配置しているので、このリストボックス・コントロールがドラッグ&ドロップを受けるようにした。これにはまず、リストボックスのAllowDropプロパティをtrueに設定しておく(29行目)。

29: listbox1.AllowDrop  = true;

DragEnterイベント・ハンドラ

 次のコードは、最初に送られてくるDragEnterイベントに関する部分を抜き出したものだ。ここではまず、DragEnterイベントに対応するイベント・ハンドラとなるメソッド(ここではlistbox1_DragEnter)を作成しておき、DragEventHandlerクラスにより作成したインスタンスをリストボックスのDragEnterイベントに追加する(30行目)。イベント・ハンドラを設定するこの手順は、ボタンがクリックされるときに呼び出されるクリック・イベント・ハンドラを設定するのと同じだ(別稿の「Windowsアプリケーションのスケルトンを知る」を参照)。

10: protected void listbox1_DragEnter(object s, DragEventArgs e) {
11:     e.Effect = DragDropEffects.All;
12: }
        ・・・
30: listbox1.DragEnter += new DragEventHandler(listbox1_DragEnter);
}

 イベント・ハンドラであるlistbox1_DragEnterメソッドでは、このコントロールが受け取ることのできる操作の種類(「コピー」や「移動」などがある)を設定する必要がある。これは2番目の引数であるDragEventArgsオブジェクトのEffectプロパティに、列挙型であるDragDropEffectsのメンバーを指定することによって行う。ここではとりあえずDragDropEffects.Allを指定しておけばよい(11行目)。

DragDropイベント・ハンドラ

 DragDropイベント・ハンドラに関する処理は次のコードである。

14: protected void listbox1_DragDrop(object s, DragEventArgs e) {
15:     if (e.Data.GetDataPresent(DataFormats.FileDrop)) {
16:         foreach (string fileName
17:                     in (string[])e.Data.GetData(DataFormats.FileDrop)) {
18:             listbox1.Items.Add(fileName);
19:         }
20:     }
21: }
        ・・・
31: listbox1.DragEnter += new DragEventHandler(listbox1_DragEnter);

 イベント・ハンドラの登録は、上記のDragEnterイベントと同様だ。このイベント・ハンドラではまず、イベントとともに受け取ったデータがファイルをドラッグしているものかどうかをチェックし、もしそうであればそのデータからファイルのフルパス名を文字列の配列として取り出す。チェックが必要な理由は、ドラッグ&ドロップされるものがファイルとは限らないためだ。Windowsでは、選択したテキストやIEのリンクなどもドラッグ&ドロップすることができる。

 イベントとともに送られる、ドラッグされたデータはDragEventArgsオブジェクトのDataプロパティに設定される。リスト中にあるe.Dataがそれで、これはDataObjectクラスのオブジェクトである(正確にはe.DataはIDataObjectインターフェイスのインターフェイス・インスタンスであり、DataObjectクラスはIDataObjectインターフェイスを実装したクラスである)。

 e.Dataのデータがファイルをドラッグ&ドロップしたものかどうかはGetDataPresentメソッドに引数としてDataFormats.FileDropを指定することによってチェックする(15行目)。DataFormats.FileDropは、ファイル・ドロップのフォーマットを示す。e.Dataのデータがこのフォーマットであれば、GetDataメソッドにより文字列の配列としてファイルのフルパス名を取り出すことができる。C#のforeach文を使用すれば、この配列内の各文字列を順番に1つずつ文字列変数であるfileNameに入れていくことができる(16、17行目)。後は各文字列をリストボックスのアイテムとして追加しているだけだ(18行目)。

 リファレンス・マニュアルでDragEventArgsクラスを調べると分かるが、DragEventArgsのプロパティにより、ユーザーによってドロップ処理が実行されたときのキー([Shift]キーや[Ctrl]キー、[Alt]キーなど)の状態や、マウス座標も得ることができる。

プログラムのコンパイル

 なお、プログラムのコンパイルは、コマンド・プロンプトから次のコマンドを実行する。

csc /r:Microsoft.Win32.Interop.DLL /r:System.DLL
/r:System.WinForms.DLL /r:System.Drawing.DLL dragdrop.cs

コンパイルが成功すればdragdrop.exeができあがる。End of Article

「C#プログラミングTips」

 



Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間