Visual Basic 6.0 初級講座 |
第26回 ドラッグ & ドロップ
今回は脅威のテクノロジー。Microsoftが誇るOLE Drag & Drop について説明します。あなたの作ったアプリケーションにMicrosoft製のほとんどのアプリケーションが装備しているドラッグ&ドロップを実装することができます。
1.ドラッグ&ドロップとは
いうまでもありませんがドラッグ&ドロップはWindowsでは頻繁に使う操作の一つです。よくファイルをマウスで引っ張ってゴミ箱に入れたりするあれです。マウスで引っ張る動作のことをドラッグ。ドラッグしているものをどこかに(たとえばゴミ箱に)落とす動作をドロップといっているわけです。
このドラッグ&ドロップのすごいところは、異なるアプリケーション間でもデータをやり取りしてしまうことです。たとえば、今あなたが読んでいるこの文章をマウスで選択して、隣に広げてるワード(Microsoft Word)にドラッグ&ドロップしてみてください。なんと、ちゃんと文字列がコピーされるではありませんか。
こんなことは普段は当たり前だと思ってファイルやら画像やら文字列やらをドラッグ&ドロップしている人もたくさんいるでしょうがこれは一体どのようにして実現されているのでしょうか?
残念ながら私はそれを説明するほどくわしくはありません。でも、VBでこのドラッグ&ドロップを装備する方法を説明することができます。
2.自動
では、前置きはこのくらにしてVBを起動して、テキストボックスをひとつ貼り付けてください。そして、ドラッグ&ドロップの練習をしたいので隣にWord(ワード)も起動しておいてください。Wordがない人はExcel(エクセル)でもいいでしょう。それもない人は一太郎でもいいかもしれません。とにかくドラッグ&ドロップできるソフトなら何でもいいです。本当に何にもない人はとりあえずこの記事を読み進めてください。最後にはあなたが作ったVBのプログラム同士でドラッグ&ドロップできるようになりますから結局後で試すことができます。
テキストボックスのプロパティで普段いじらないようなものもたくさんあるのですが、その中のOLEDragModeプロパティ(オーエルイードラッグモード)を 1-自動 にして下さい。
これだけで完成です。・・・さすがVBはこういう操作はやりやすい。
試してみてください。プログラムを実行してテキストボックスの中の文字列をすべて選択してください。そして、その文字列を隣のWord(とか)にドラッグしてドロップしてみてください。どうです?文字列がコピーされたでしょう。
逆もできます。逆をやるには今度はテキストボックスのOLEDropModeプロパティ (オーエルイードロップモード)を 1-自動にします。これだけでWordの文字列をドラッグしてテキストボックスにドロップできるようになります。
さらに、もう1つテキストボックスを追加してこれもOLEDragModeプロパティとOLEDropModeプロパティをTrueにしてみましょう。そうすると今度はVBのテキストボックス同士でドラッグ&ドロップできるようになります。
プロパティの操作だけでこんなことができるのですから便利な世の中になったものです。
文字だけじゃ面白くありません。画像でも試してみましょう。PictureBoxをはりつけて何でもいいから画像を表示させてください。(念のため。PictureBoxに画像を表示させる一番簡単な方法は Pictureプロパティをデザイン時に設定する方法です)
さて、このPictureBoxのOLEDragModeプロパティを 1-自動 にすればもう表示されている画像をドラッグだけでWordにコピーすることができます。
さらに細かくドラッグ&ドロップを制御したい場合は 0-手動 という選択肢もあります。これについては次から触れます。
3.ファイルのドラッグ&ドロップ
ファイルをドラッグ&ドロップで受け入れるアプリケーションもよく見かけられます。もちろんVBでもできますが、さすがにプロパティだけで済ませるわけには行きません。実験してみましょう。
フォームにリストボックスを1つ貼り付けてください。OLEDropModeを 0-手動 にしましょう。これだけで実行してみると意見ファイルをドロップできそうな様子を示すのですが実際にドロップしても何も起きません。この場合はドロップされた場合の処理を自分で書く必要があります。
ファイル(や画像やテキストなど)がドロップされてくるとイベントが発生します。OLEDragDropイベント(オーエルイードラッグドロップ)です。
早速このイベントプロシージャを生成してみてください。分からない人のために手順を書きますと、リストボックスをダブルクリックしてコード入力画面に切り替わったらプロシージャボックス(画面参照)から、OLEDragDropを選びます。
そうすると次のようなコードが自動的に生成されます。
Private Sub List1_OLEDragDrop(Data As DataObject, Effect As Long, Button As
Integer, Shift As Integer, X As Single, Y As Single)
End Sub
このイベントプロシージャにためしにMsgBox "Hello!"と書いて実行してみてください。ドロップすると"Hello!"と表示されるでしょう。
では、何がドロップされたか知るにはどうしたらよいでしょうか。これにはData引数を使います。
次のように記述してみてください。
Private Sub List1_OLEDragDrop(Data
As DataObject, Effect As Long, Button
As Integer, Shift As Integer, X
As Single, Y As Single) Dim K As Long If Data.GetFormat(vbCFFiles) Then For K = 1 To Data.Files.Count List1.AddItem Data.Files(K) Next K End If End Sub |
これで実行してみるとリストボックスにはちゃんとドロップしたファイル名が表示されます。複数のファイルを同時にドロップしてもしっかり対応していますから試してみてください。さらにフォルダも大丈夫です。
では、このコードを解説しましょう。はじめの If Data.GetFormat(vbCFFiles) Then ではドロップされたものがファイルかどうか確認しています。ドロップされたのがファイルなら Data.GetFormat(vbCFFiles) はTrueを、そうでないならFalseを返します。GetFormat関数の引数には vbCFFilesの他にビットマップかどうか確認するvbCFBitmapやテキストかどうか確認するvbCFTextなどが使えます。すべて知りたい人はVBで vbCFFiles のところにカーソルを置いて F1 を押してヘルプを表示させるか Shift + F2 を押してオブジェクトブラウザを起動してください。
ファイルであった場合には「いくつのファイルがドロップされたのか」を確認してすべてのファイルを表示します。ファイルの数を知るには DataObjectオブジェクトのFilesコレクションを使います。具体的には上の例のように Data.Files.Count を使います。個々のファイル名を取得するには Data.Files(1) のようにします。注意してほしいのは Filesは配列ではなくコレクションであるということ、それに0ではなく1から始まるということです。
以上。初めての人には一瞬「むっ?」とした人もいたかもしれませんが比較的簡単なコードでドラッグ&ドロップが実装できることがお分かりいただけたと思います。
4.ドラッグ&ドロップでの起動
よくファイルをアイコンにドロップすることでプログラムを起動する人がいますね。私もその一人です。Lhasaなどの解凍ソフトには圧縮ファイルをドロップするだけで勝手に解凍してくれる機能があるのでとりわけ便利です。他にもWordやExcelのアイコンに.docや.xlsをドロップしてもファイルを開くことができるし、この機能はメモ帳なのにもついています。
では、あなたがVBで作ったアプリケーションでは?フォームのOLEDragDropイベントが発生しているのでしょうか?
実はこの「アイコンにドラッグ&ドロップ」という操作は同じ「ドラッグ&ドロップ」といってもさっき解説した「ドラッグ&ドロップ」とは別のテクノロジーなのです。実はこれ、単なるコマンドラインを指定した起動なのです。ここで「コマンドライン」を知らなかった人も恐れる必要はありません。簡単なことです。
フォームのLoadイベントに次のように書いてください。
Private Sub Form_Load()
End Sub |
これで、起動するときにドロップされたファイルの名前を表示してくれます。もっともこのコードを本当に試すには一回コンパイルする必要があるのでVBの評価版(試用版)を使っている人にはちょっと申し訳ないです。
ここでいいたかったのはCommand関数を使えばアイコンにドロップされたファイル名が分かるということです。またファイル名以外のものが指定された場合にもCommand関数で取得できます。このあたりのことは今回は説明しません。
ちなみに複数のファイルがドロップされた場合はどうなのでしょうか?この場合はCommand関数はファイルとファイルの間を半角スペースで区切って返してきます。ですから、ファイル名に半角スペースが含まれている場合には処理が大変です。それにどのみちこの方法では256文字くらいが限界なので大量のファイルをドロップするなぞ無理です。割り切って使ってください。
5.発展への予備知識
本当はこのあたりで「最後に」したいところなのです。ここのところ連日暑くてクーラーのない私の部屋でパソコンに向かっているのが嫌なのです。でも、どうしても説明しておかなければいけないことがあるのでがんばって書きます。
ドラッグ時に OLEDragModeプロパティ 0-手動 にしている場合は今までざっと説明した以上の細かい制御が可能です。
これはドラッグ時にOLEStartDragイベントが発生することにより実現します。OLEStartDragイベントの引数であるDataObjectオブジェクトのSetDataメソッドを使うことで「ドラッグされるものの内容」を自分でセットすることができます。
さらに、ドラッグ中に次々と発生するOLEDragOverイベント、OLEGiveFeedbackイベントを利用すれば相当効果的な処理を記述することも可能でしょう。ただし私はそこまで請ったことはないのでこの2つのイベントは試し程度にしか使ったことはありません。
ぐだぐだ書いていてもよく分からないと思うので最後にサンプルを示しましょう。
このサンプルはあなたの画像ファイル(jpegやgif)をbmpに変換するか、削除するかします。どちらにするかはあなたがドラッグ&ドロップで決めます。
フォーム上にはラベルが2つ張り付いていて、1つには「BMP」、1つには「削除」と書かれています。このどちらかに画像をドロップすれば言いわけです。画像はピクチャーボックスにあらかじめ読み込んだものをドラッグすることになります。外部からのドロップは受け付けません。
フォームに貼り付けるもの
Picture1 (PictureBox)
OLEDragModeプロパティを 0-手動 に設定する。
lblBmp (Label)
Captionプロパティを "BMP" に設定する。
OLEDropModeプロパティを 0-手動 に設定する。
lblDelete(Label)
Captionプロパティを "削除" に設定する。
OLEDropModeプロパティを 0-手動 に設定する。
Text1 (TextBox)
Captionプロパティを空にする。
OLEDropModeプロパティを 1-自動 に設定する。
cmdOpen (Command)
Captionプロパティを "開く" に設定する。
CommonDialog1 (CommonDialog)
Filterプロパティに "画像ファイル(*.gif,*.jpg,*.jpeg)|*.jpeg;*.jpg;*.gif" と設定する。
準備が整ったら次のコードを記述します。(もちろんマウスで選択して、まるごとコピー・貼り付けで結構です)。
Option Explicit
Dim FileName As StringPrivate Sub cmdOpen_Click()
On Error Resume Next
CommonDialog1.ShowOpen
If Len(CommonDialog1.FileName) = 0 Then Exit Sub
FileName = CommonDialog1.FileName
Picture1.Picture = LoadPicture(FileName)
End SubPrivate Sub lblBmp_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim TargetName As String
'●BMPとして保存する。
'ここでドラッグされた画像ではなく画像のファイル名を取得できるのは
'自分で Data.SetData FileName, vbCFText を記述したから。
TargetName = Data.GetData(vbCFText)
TargetName = Left(TargetName, Len(TargetName) - 4) & ".bmp"
SavePicture Picture1.Picture, TargetName
End SubPrivate Sub lblDelete_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single)
Dim TargetName As String
'●ファイルを削除する。
TargetName = Data.GetData(vbCFText)
Kill TargetName
Picture1.Picture = LoadPicture("")
End SubPrivate Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Picture1.OLEDrag 'ドラッグ開始
End SubPrivate Sub Picture1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
'ドラッグ開始時にここが呼び出される。
'Dataにはドラッグされる「画像」ではなく画像の「ファイル名」を渡す。
'ここがこのサンプルで一番言いたい場所。
Data.SetData FileName, vbCFText
AllowedEffects = vbDropEffectCopy 'ドロップによるコピーを許可する。
End Sub
ここで解読するよりは実際に作って実行したほうが話が早いと思います。手動でのドラッグ&ドロップの簡単な例としてご活用ください。
なお、削除したファイルは元に戻りませんのでくれぐれもご注意を。
6.最後に
聞いた話ではOLEDrag&Dropのような機能をLinux(リナックス)で実装するのは困難ということです。普段何気なく使っているこの機能ですがあなたのアプリケーションにうまく搭載できれば、ユーザーは普段Windowsを操作するのと変わらぬ操作感であなたのアプリケーションを使用することができます。
他にもいろいろ便利な使い方ができそうでしょう?工夫してみてください。