今回はドラッグアンドドロップされたファイルのパスを知る方法を解説します。
これ、C言語でやろうとすると結構大変です。以下はC言語でWindowsアプリケーションをつくるときに参考にしていたお気に入りのサイトです。
しかしC#であれば簡単にできてしまいます。
まずは本当に鳩でも分かるC#講座をやってみるにあるように、「新しいプロジェクトの作成」を選択して、「Winndows フォームアプリ」を選択、ターゲットフレームワークは「.NET5.0」を選択します。
フォームにドラッグアンドドロップされたファイルを取得するだけであれば簡単なコードで実現できます。
まずAllowDropプロパティをtrueにしておきましょう。またはForm1クラスのコンストラクタで以下のように書いてもかまいません。namespace WinFormsApp1の部分はプロジェクトをつくるときに入力する文字列で変化します。以降はこの部分は省略します。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
namespace WinFormsApp1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); // ここに記述する this.AllowDrop = true; } } } |
次になにかがドラッグされたときに発生するイベントがあるので、プロパティからイベントハンドラを追加します。上の画像のDragOverとDragDropと書かれている部分をダブルクリックすると以下のようなコードが自動的に追加されます。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { private void Form1_DragOver(object sender, DragEventArgs e) { } private void Form1_DragDrop(object sender, DragEventArgs e) { } } |
またはこのようなものに頼らず自分で追加する方法もあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.AllowDrop = true; // デザイナの機能をつかわず自分で追加した DragOver += Form1_DragOver; DragDrop += Form1_DragDrop; } private void Form1_DragDrop(object sender, DragEventArgs e) { // この部分は削除しましょう throw new NotImplementedException(); } private void Form1_DragOver(object sender, DragEventArgs e) { // この部分は削除しましょう throw new NotImplementedException(); } } |
それからForm.OnDragOverメソッドとForm.OnDragDropメソッドをオーバーライドする方法もあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
public partial class Form1 : Form { public Form1() { InitializeComponent(); this.AllowDrop = true; } protected override void OnDragOver(DragEventArgs drgevent) { // 以下の1文はなくてもよいがあったほうがよい base.OnDragOver(drgevent); } protected override void OnDragDrop(DragEventArgs drgevent) { // 以下の1文はなくてもよいがあったほうがよい base.OnDragOver(drgevent); } } |
どれもこのメソッド内に追加するコードはかわりません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// デザイナが生成した void Form1_DragOver(object sender, DragEventArgs e)の場合も同様 protected override void OnDragOver(DragEventArgs drgevent) { if(drgevent.Data.GetDataPresent(DataFormats.FileDrop)) drgevent.Effect = DragDropEffects.Copy; else drgevent.Effect = DragDropEffects.None; base.OnDragOver(drgevent); } // デザイナが生成した void Form1_DragDrop(object sender, DragEventArgs e)の場合も同様 protected override void OnDragDrop(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(DataFormats.FileDrop)) { string[] filePaths = (string[])drgevent.Data.GetData(DataFormats.FileDrop); // 取得したファイルパスでやりたいことをする } base.OnDragDrop(drgevent); } |
DragOverイベントとDragDropイベントの処理
OnDragOverはなにかがフォームの上をドラッグされているときに呼び出されます。ファイルがドラッグされているか知りたいのであれば、メソッドの引数のあとにData.GetDataPresent(DataFormats.FileDrop)を付け加えて条件式をつくれば、それがファイルやフォルダであるかどうかを知ることができます。
ファイルやフォルダであるならマウスポインタをコピー可能があることを示すタイプのものに変更します。それ以外のデータであればDragDropEffects.None;と書かれているため、禁止の形をしたマウスポインタが表示されます。
ファイルやフォルダであるならドロップされたときにOnDragDropメソッドが呼び出されます。
if文でドロップされたものがファイルまたはフォルダであることを確認してdrgevent.Data.GetData(DataFormats.FileDrop);を実行、戻り値をstringの配列型にキャストして変数に格納します。これでfilePathsにはフォーム上にドロップされたファイルやフォルダのパスが格納されます。
画像ファイルがドロップされたら表示させる
ではこのデータをつかってなにか面白いことをしてみましょう。
もし画像ファイルがドロップされたら画像が表示されるというのはどうでしょうか? サンプルプログラムとしてはまあまあ面白いのではないかと思われます。
ではツールボックスからPictureBoxをフォームにドラッグアンドドロップしましょう。そして適当な大きさに調整します。PictureBoxの名前はpictureBox1にします(自分で変更しなくても自動でこんな感じの名前になります)。
そしてOnDragDropメソッド(Form1_DragDrop(object sender, DragEventArgs eでも同様)を以下のように変更します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
protected override void OnDragDrop(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(DataFormats.FileDrop)) { string[] filePaths = (string[])drgevent.Data.GetData(DataFormats.FileDrop); // ファイルからBitmapオブジェクトを取得してPictureBox.Imageにセット Image image = Image.FromFile(filePaths[0]); Bitmap bitmap = new Bitmap(image); image.Dispose(); pictureBox1.Image = bitmap; } base.OnDragOver(drgevent); } |
Image.FromFileメソッドに画像ファイルのパスを渡すとImageを取得することができます。これをそのままpictureBox1.Imageにセットしてもよいのですが、これだとプログラムが終了するまでこのファイルがロックされた状態になり、他のアプリで使用することができなくなります。
なのでいったんImage.FromFileで取得したものからコピーを生成しています。これならimage.Dispose()を実行したあとロックが解除されるので問題はありません。
ただ上記のコードはドラッグされたファイルが常に画像ファイルであるという前提のもと作られています。実際にはそんな前提はありません。テキストファイルやフォルダがドロップされることも考えられます。このような場合、例外が発生してプログラムがとまってしまうので対策をしておく必要があります。
そこで以下のように書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
protected override void OnDragDrop(DragEventArgs drgevent) { if (drgevent.Data.GetDataPresent(DataFormats.FileDrop)) { string[] filePaths = (string[])drgevent.Data.GetData(DataFormats.FileDrop); try { // 例外が発生するかもしれない処理 Image image = Image.FromFile(filePaths[0]); Bitmap bitmap = new Bitmap(image); image.Dispose(); pictureBox1.Image = bitmap; } catch { // 例外が発生したときの処理 MessageBox.Show("エラーです。そのファイルは本当に画像ファイルですか?"); } } base.OnDragOver(drgevent); } |
これで不適切なファイルがドロップされたときにエラーを示すメッセージボックスが表示されるようになります。