.NET TIPS

ファイルやディレクトリをエクスプローラへドラッグ&ドロップするには?

デジタルアドバンテージ 一色 政彦
2005/12/09


 Windowsアプリケーションでは、ツリービューやリストビューなどで選択された項目を別のアプリケーションへドラッグ&ドロップにより伝えることができる。この機能を使えば、例えば自作アプリケーションのツリービューに表示されたディレクトリの項目をWindowsのエクスプローラへドラッグ&ドロップして、そのディレクトリを実際に「コピー」「移動」するといったことが可能だ。

 そこで本稿では、このようなエクスプローラへのファイルやディレクトリのドラッグ&ドロップを可能にする方法を解説する(なおエクスプローラの基本機能では、ファイルやディレクトリをドラッグ&ドロップする場合、[Ctrl]キーを押しながらドラッグ&ドロップすると「コピー」、[Shift]キーを押しながら行うと「移動」になる。何もキーを押さなければ基本的に「移動」になる)。

 次の画面は、本稿で作成するWindowsアプリケーションのサンプル・プログラムである。このアプリケーションでは、エクスプローラの左側にあるツリー表示と同じように、利用可能なドライブとその配下にあるディレクトリの一覧を表示する。

本稿で作成するサンプル・アプリケーション
ディレクトリ一覧をツリー表示するだけのシンプルなアプリケーションである。このツリー項目の1つをエクスプローラへドラッグ&ドロップすると、実際にそのディレクトリが移動する。

 このアプリケーションは、起動時にマイ・コンピュータ以下のドライブを列挙し、そのドライブやその下位のフォルダを開くたびにサブ・フォルダの項目を追加して表示する。詳しいプログラムのソース・コードの内容解説は割愛するが、ドライブの列挙については「TIPS:利用可能なドライブの一覧を取得するには?」を、ディレクトリの列挙については「TIPS:ファイルやディレクトリの一覧を取得するには?」を、TreeViewコントロールに適宜サブ・フォルダを追加する方法については「TIPS:TreeViewコントロールで効率的にツリーを構築するには?」を参照されたい。

 それではさっそくこのアプリケーションを実装してみよう。

エクスプローラへのドラッグ&ドロップに対応するには?

 TreeViewコントロールもしくはListViewコントロールの項目をドラッグ&ドロップできるようにするには、まずプログラムにItemDragイベント・ハンドラを追加して、次にそのイベント・ハンドラ内にドラッグ&ドロップを実行するためのコードを記述する。

 ItemDragイベント・ハンドラの追加は難しくないのでここでは説明を割愛する。なおItemDragイベントは、ユーザーがTreeViewコントロールもしくはListViewコントロール内の項目をドラッグし始めたときに発生するイベントである。これら以外のコントロールでドラッグ&ドロップに対応する場合、ItemDragイベントが発生しないので、代わりにMouseDownイベント・ハンドラを追加して、その中にドラッグ&ドロップを実行するコードを記述する必要がある(本稿ではMouseDownイベント・ハンドラの実装については割愛する)。

 次にItemDragイベント・ハンドラ内に項目をドラッグ&ドロップする機能を実装しなければならないが、これはコントロールのDoDragDropメソッドがすべて実現してくれる。つまりここでは、TreeViewコントロールのDoDragDropメソッドを呼び出せば、ドラッグ&ドロップの実装は完了である。

 DoDragDropメソッドには、第1パラメータにドラッグ&ドロップするデータを、第2パラメータにはドラッグ&ドロップ時に可能な操作(=効果:Effect)を示す値を指定する(詳細後述)。メソッドの戻り値としては、(第2パラメータに指定したもののうち)操作中に実際に実行された効果の値が返される仕様になっている(ただしエクスプローラへドラッグ&ドロップした場合などでは、必ずしもこの値は正しくないようなので、この戻り値はあまり信用できない)。

●第1パラメータ:ドラッグ&ドロップするデータ

 DoDragDropメソッドの第1パラメータのデータには、Object型の値が指定できる。このことは、ドラッグ&ドロップするデータとしてどのような型のデータでも指定できることを意味する。例えばアプリケーション内部でシンプルな文字列データだけを転送したいというようなケースなら、単にString型のデータを渡せばよい。

 本稿のサンプル・プログラムでは、ディレクトリやファイルのデータをエクスプローラにドラッグ&ドロップにより転送したいので、エクスプローラが認識できる特殊なデータ・オブジェクトを作成する必要がある。このデータ・オブジェクトは、System.Windows.Forms名前空間のDataObjectクラスにより作成できる(なお同じ名前のクラスがSystem.Security.Cryptography.Xml名前空間にも存在するので注意すること)。このDataObjectクラスは、基本的なデータ転送機構を備えており、クリップボードやドラッグ&ドロップ操作でのデータ転送に使われる。

 実際にDataObjectクラスを利用するには、DataObjectクラスのコンストラクタの第1パラメータにデータ・フォーマットを指定し、第2パラメータに実際のデータを指定して、それをインスタンス化(new)する。

 第1パラメータのデータ・フォーマットには、DataFormatsクラス(System.Windows.Forms名前空間)のフィールドの値を指定できる。本稿の場合では、エクスプローラが利用できる「Windowsファイル・ドロップ形式」(DataFormats.FileDropフィールド)を指定しなければならない。データ・フォーマットには数多くの種類が用意されているが、ここではその内容については割愛する。詳しくはMSDNの「DataFormatsフィールド」を参照してほしい。

 第2パラメータには実際のデータを指定するが、本稿のように第1パラメータにDataFormats.FileDropを指定した場合は、ファイルのパス名を文字列配列として指定すればよい(転送するデータとして複数のパス名を指定できる)。

 DataObjectクラスのインスタンス化部分を実装すると次のようなコードになる。

string[] paths = { @"C:\test" }; // ファイル・パスの文字列配列
DataObject dataObj = new DataObject(DataFormats.FileDrop, paths);
Dim paths() As String = { "C:\test" } ' ファイル・パスの文字列配列
Dim dataObj As New DataObject(DataFormats.FileDrop, paths)
DataObjectクラスのインスタンス化(上:C#、下:VB.NET)

 このようにして作成した転送用のデータ・オブジェクトを、DoDragDropメソッドの第1パラメータに指定すればよい。

●第2パラメータ:DragDropEffects列挙体の値

 DoDragDropメソッドの第2パラメータに指定するドラッグ&ドロップで可能な操作を示す値は、具体的にはDragDropEffects列挙体(System.Windows.Forms名前空間)の値である。この値はビット演算で組み合わせることができる。例えば「コピー」と「移動」を許可するならば、次のように記述すればよい。

effect = DragDropEffects.Copy | DragDropEffects.Move;
effect = DragDropEffects.Copy Or DragDropEffects.Move
DragDropEffects列挙体の値をビット演算で組み合わせる例(上:C#、下:VB.NET)
この例では、ドラッグ&ドロップで可能な操作として「コピー」(Copy)と「移動」(Move)をビット演算で組み合わせた値を、変数effectに代入している。effectはDragDropEffects型の変数である。

 DragDropEffects列挙体の値の意味については以下の表を参照してほしい。

DragDropEffects列挙体 基本的なマウス形状 実際の数値 説明
Copy
1 コピー。データがドロップ先にコピーされようとしている状態
Move
2 移動。データがドロップ先に移動されようとしている状態
Scroll
-2147483648 スクロール。データによってドロップ先でスクロールが開始されようとしている状態、あるいは現在スクロール中である状態(※)
All
-2147483645 すべて。上の3つを組み合わせたもの(Copy+Move+Scroll)。ドロップ先で、データがコピーされたり、移動されたり、スクロールが発生したりする状態
Link
4 ショートカット(などのリンク)の作成。データのリンクがドロップ先に作成されようとしている状態
None
0 効果なし。いかなるデータもドロップ先が受け付けようとしない状態
DragDropEffects列挙体の値の意味
DragDropEffects.Scrollは、例えばスクロール・バーのように、つまみをドラッグしてウィンドウの表示領域をスクロールさせたりするのに使用する。実際にスクロールさせるには、コピー<元>コントロールのGiveFeedbackイベント・ハンドラを追加してその中で行えばよい。しかしこのような機能はすでにWindowsコントロールに備わっているので、ほとんど使うことはないだろう。

●エクスプローラへのドラッグ&ドロップに対応したサンプル・プログラム

 以上の内容を実装したのが次のコードだ。

private void treeView1_ItemDrag(object sender, System.Windows.Forms.ItemDragEventArgs e)
{
  string path = GetPathFromNode(((TreeNode)e.Item));
  string[] paths = { path };
  DataObject dataObj = new DataObject(DataFormats.FileDrop, paths);
  DragDropEffects effect =
    DragDropEffects.Copy |DragDropEffects.Move;
  treeView1.DoDragDrop(dataObj, effect);
}

// ノードからパスを取得します。
private string GetPathFromNode(TreeNode node)
{
  if (node.Parent == null)
  {
    return node.Text;
  }
  return Path.Combine(GetPathFromNode(node.Parent), node.Text);
}
Private Sub TreeView1_ItemDrag(ByVal sender As Object, ByVal e As System.Windows.Forms.ItemDragEventArgs) Handles treeView1.ItemDrag
  Dim path As String = GetPathFromNode((CType(e.Item, TreeNode)))
  Dim paths() As String = { path }
  Dim dataObj As New DataObject(DataFormats.FileDrop, paths)
  Dim effect As DragDropEffects = _
    DragDropEffects.Copy Or DragDropEffects.Move
  treeView1.DoDragDrop(dataObj, effect)
End Sub

' ノードからパスを取得します。

Private Function GetPathFromNode(ByVal node As TreeNode) As String
  If node.Parent Is Nothing Then
    Return node.Text
  End If
  Return Path.Combine(GetPathFromNode(node.Parent), node.Text)
End Function
エクスプローラへのドラッグ&ドロップに対応したサンプル・プログラム(上:C#、下:VB.NET)

 そしてこのプログラムを実行しているのが次の画面だ。

サンプル・プログラムの実行結果
起動したアプリケーションのTreeViewコントロールから「C:\tip」ディレクトリ項目をエクスプローラ上にドラッグ&ドロップしているところ。このままドロップするとそのディレクトリが実際に「移動」する。なおドラッグ中に、[Ctrl]キーを押すと「コピー」を表すマウス形状にに変化し、その形状のままドロップすると実際にその操作(コピー)が実行される。なおエクスプローラでは、[Ctrl]キー+[Shift]キーを押しながら、もしくは[Alt]キーを押しながらドラッグ&ドロップすると「リンク」(=ショートカット)を作成することができるが、本稿の方法ではエラーが出るので「DragDropEffects.Link」には対応しなかった。

 実行したアプリケーションのTreeViewコントロールからディレクトリの項目をエクスプローラにドラッグ&ドロップすると、実際にフォルダが「移動」する。またドラッグ中に[Ctrl]キーを押してそのままドロップするとそのフォルダは「コピー」されることになる。このような「移動」「コピー」などの処理自体は、本稿のアプリケーションが実行しているわけではない。ドラッグ&ドロップの実際の処理はエクスプローラが行っているのである。End of Article

カテゴリ:Windowsフォーム 処理対象:コントロール
使用ライブラリ:TreeViewクラス(System.Windows.Forms名前空間)
使用ライブラリ:DataObjectクラス(System.Windows.Forms名前空間)
使用ライブラリ:DataFormatsクラス(System.Windows.Forms名前空間)
関連TIPS:利用可能なドライブの一覧を取得するには?
関連TIPS:ファイルやディレクトリの一覧を取得するには?
関連TIPS:TreeViewコントロールで効率的にツリーを構築するには?

この記事と関連性の高い別の.NET TIPS
Webブラウザ上のアドレスをドラッグ&ドロップで取得するには?
エクスプローラからファイルをドラッグ&ドロップできるようにするには?
Visual Studioのメニューやツールバーをカスタマイズするには?
[ASP.NET]ページから生成されたソース・コードを見るには?
ファイルやディレクトリの作成/変更/削除を監視するには?
このリストは、(株)デジタルアドバンテージが開発した
自動関連記事探索システム Jigsaw(ジグソー) により自動抽出したものです。
generated by

「.NET 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 記事ランキング

本日 月間