プログラム講座 中級編22

- 簡易ドラッグドロップ -

 中級編22です。今回は「簡易ドラッグドロップの方法」について説明します。




簡易ドラッグドロップ
 簡易とつけているのは理由があって、この機構は元々System 7以前でも使用できるものだからです。正確に言えばアップルイベントを利用したものではなく「ファイル選択してファイルメニューの開く...」を選択した場合と同じとも言えます。このため、アプリケーション起動後にドラッグドロップしてもドラッグドロップされたファイルを認識させることは出来ません。
 アップルイベントを利用してドラッグドロップさせるには、全く別の機構が必要になります。これについては、上級編で解説したいと思います。
 KT7.5以降でサポートされたテキストエディタ内からのドラッグドロップ(テキストクリッピング、ピクチャークリッピング)についても別の機構が必要になりますが、これに関してはモードから発売されているFuture BASIC TOOLSを利用することで可能になります。ただし、FBのバージョンが2.3でないと使用することが出来ません。



ファインダからの情報を得るには?
 簡易ドラッグドロップは非常に手軽に実現できます。今回はドラッグドロップされたファイル数が複数ある場合でも最初の1つしか処理しない事にします。これによりプログラムで何をしているのか容易に分かるからです。
 ドラッグドロップを実現するための命令は以下のものです。

FINDERINFO(最大ファイル数,ファイル名,ファイルタイプ,ボリューム参照番号)

 このFINDERINFOを使うとドラッグドロップされたファイル名やファイルタイプ、ファイル数を求めることが出来ます。
 「最大ファイル数」は「受け取る最大ファイル数」を指定します。処理が終わると「ドラッグドロップされたファイル数」を返すようになっています。つまり複数ファイルの場合はFOR I=1 to maxFiles%〜NEXTのようにすればドラッグドロップされたファイルを処理することが出来ます。
 「ファイル名」はドラッグドロップされたファイル名を返します。複数のファイルを受け取る場合は配列にしておきます。
 「ファイルタイプ」はドラッグドロップされたファイルのファイルタイプを返します。このファイルタイプはあらかじめリソースエディタで指定しておきます。これについては次の項で説明します。
 「ボリューム参照番号」はファイルが存在するボリューム参照番号を返します。

 実際のドラッグドロップを行うプログラムは以下のようになります。

LOCAL FN dragDrop
maxFile% = 1
theType = FINDERINFO(maxFile%,filename$,fileType&,vRefNum%)
IF maxFile% THEN FN theLF(_MactoMSDOS,filename$,vRefNum%)
END FN

 今回は改行コード変換のプログラムでドラッグドロップされたファイルを自動的に処理するようにしています。このドラッグドロップを呼び出す位置ですが、メインループに入る前、HANDLEEVENTSループの前にFN dragDropとして呼び出すのがよいでしょう。HANDLEEVENTSループに入れても意味がありません。



リソースエディタの設定
 ドラッグドロップを実現させるためにはリソースエディタの助けが必要です。ただし、単純に自分で作成した独自のファイルのみであれば何も設定する必要はありません。リソースエディタで設定しなければいけないのはテキストファイルやPICTファイルをドラッグドロップしたい場合です。
 まずBNDLリソースを作成します。



 次に「????」となっている所に自分のアプリケーションの「クリエーター」を入力します(4文字です)。RESOURCES文の第2引数(RESOURCES "theLF.res","APPLcvds")のcvdsを入力します。



 次にドラッグドロップ可能なファイルタイプを設定します。RESOURCEメニューから「Create New File Type」を選択します。



 「????」となっている所に「ファイルタイプ」を入力します(4文字です。リターンキーを押す必要はありません)。



 今回は改行コード変換ですのでドラッグドロップ可能なファイルはテキスト(TEXT)のみです。以下にファイルタイプを載せておきますので参考にして下さい。

ファイルタイプ種  類
TEXTテキストファイル
EPSFEPS(ポストスクリプトファイル,イラストレーターファイル)
MidiMIDIファイル
PNTGMacPaintファイル
TIFFTIFF形式ファイル
PICTPICTファイル
DISKフォルダ
****全ての種類のファイル

 特定の2種類のファイルのみドラッグドロップ可能にしたい場合は、RESOURCEメニューの「CREATE NEW FILE TYPE」で新しくファイルタイプを追加して設定を行います。



終わりに
 作成したリソースを連結してコンパイルしビルド(アプリケーション作成)すれば、すぐにドラッグドロップ可能になります。もし、ドラッグドロップできない場合はドラッグドロップするファイルとドラッグドロップ可能なファイルタイプと一致しているか、正常にファイルタイプが設定されているか確認してください。それでも駄目な場合は「デスクトップファイル」を作りなおして下さい。デスクトップファイルを作りなおすには再起動後option+Commandキーを同時に押したままにします。ダイアログが表示されますので再構築をしてください。それでも駄目な場合はプログラムが間違っているかリソースの設定が間違っています。もう一度確認してみましょう。
 これで何となくMacらしいアプリケーションを作ることが可能になるはずです。あとは起動中にもドラッグドロップ可能になれば完璧です。これは別の方法を使うことになりますので別の章にて解説したいと思います。



今回のプログラムリスト
'--------------------------------------------------------------------- ' "改行コードを変換します" ' "CR (13) -> CRLF (10,13)" '--------------------------------------------------------------------- OUTPUT FILE "convertDOS": ' "作成するアプリケーション名の指定" RESOURCES "theLF.res","APPLcvds": ' "リソースを連結します" _crCode = 13: '"Macの改行コードはアスキーコードで13" _lfCode = 10: '"MS-DOS(Windows)の改行コードはアスキーコードで10,13" _MSDOStoMac = 0 _MactoMSDOS = 1 _memoryError = 257: ' "メモリ不足のアラート" gQuit_flag = _false: '"終了フラグ" END GLOBALS '--------------------------------------------------------------------- ' "テキスト変換の中核部分の処理(改行コードを付加)" ' "switch = _falseであればDOSテキストに変換" ' "switch = _trueであればMacテキストに変換" '--------------------------------------------------------------------- LOCAL FN theLF(switch,openfile$,openRefNum%) LONG IF openfile$ = "" openfile$ = FILES$(_fOpen,"TEXT",,openRefNum%):' "ファイル選択ダイアログの表示" END IF LONG IF openfile$<>"" savefile$ = FILES$(_fSave,"ファイル名","",saveRefNum%):' "ファイル保存ダイアログの表示" LONG IF savefile$<>"" DEF OPEN "TEXTttxt": ' "TeachText/SimpleText形式で保存" OPEN "I",#1,openfile$,,openRefNum%: ' "変換元のファイルをオープン" fileSize& = LOF(1,1): ' "ファイルサイズを求める" myHandle& = FN NEWHANDLE(fileSize&): ' "ファイルサイズ分メモリを確保します!" convHandle& = FN NEWHANDLE(fileSize&*2): ' "変換サイズ分メモリを確保します!" count& = 0: ' "書き出すバイト数をクリア" LONG IF myHandle& = 0 OR convHandle& = 0: ' "ハンドルサイズが0の時はメモリ不足で確保できなかった!" CALL PARAMTEXT("メモリ不足で変換できませんf(-.-b","","","") err% = FN ALERT(_memoryError,0): ' "ファイルサイズが巨大なため読み込むことが出来ません" XELSE err% = FN HLOCK(myHandle&): ' "メモリが移動しないようにハンドルをロック" err% = FN HLOCK(convHandle&): ' "メモリが移動しないようにハンドルをロック" READ FILE #1,[myHandle&],fileSize&: ' "ファイルを読み込む" CLOSE #1 pointer& = [convHandle&]: ' "ポインタを求める" FOR i& = 0 TO fileSize&-1: ' "ファイルサイズ分繰り返す" code% = PEEK([myHandle&] + i&): ' "1バイト読み込む" POKE pointer&,code%: ' "変換後のメモリに1バイト書き込む" pointer& = pointer& + 1 count& = count& + 1 SELECT switch CASE _MSDOStoMac: ' "MS-DOS -> Mac" LONG IF code% = _lfCode pointer& = pointer& - 1: ' "アドレスを1つ減少させ次のコードが上書きされるようにする" count& = count& - 1 END IF CASE _MactoMSDOS: ' "Mac -> MS-DOS" LONG IF code% = _crCode POKE pointer&,_lfCode: ' "改行コードがCRだったらLFを追加する" pointer& = pointer& + 1: ' "アドレスを1つ増加" count& = count& + 1 END IF END SELECT NEXT OPEN "O",#1,savefile$,,saveRefNum%: ' "変換先のファイルをオープン" WRITE FILE #1,[convHandle&],count&: ' "ファイルを書き込む" CLOSE #1 END IF DEF DISPOSEH(myHandle&): ' "確保したメモリを解放する" DEF DISPOSEH(convHandle&): ' "確保したメモリを解放する" END IF END IF END FN '--------------------------------------------------------------------- ' "メニューの初期化:アバウト画面は手抜きのためなしf(^^b" '--------------------------------------------------------------------- LOCAL FN initMenu MENU 1,0,_enable,"ファイル" MENU 1,1,_enable,"MacからMS-DOSの改行コードに変換..." MENU 1,2,_enable,"MS-DOSからMacの改行コードに変換..." MENU 1,3,_disable,";" MENU 1,4,_enable,"/Q終了" END FN '--------------------------------------------------------------------- ' "選択されたメニューに応じて処理を振り分けます" '--------------------------------------------------------------------- LOCAL FN doMenu menuID = MENU(_menuID): '"メニューバーのどの項目かな?" itemID = MENU(_itemID): '"プルダウンメニューのどの項目かな?" SELECT menuID: '"まずは、どのメニューバーか調べます" CASE 1 SELECT itemID CASE 1 FN theLF(_MSDOStoMac,"",0): '"改行コードを付加" CASE 2 FN theLF(_MactoMSDOS,"",0): '"改行コードを削除" CASE 4 gQuit_flag = _true: '"終了スイッチオン" END SELECT END SELECT MENU: '"メニューのハイライトを戻します" END FN '--------------------------------------------------------------------- ' "ドラッグされたファイルを調べます" ' "Mac -> MS-DOSへの変換のみ行います" '--------------------------------------------------------------------- LOCAL FN dragDrop maxFile% = 1 theType = FINDERINFO(maxFile%,filename$,fileType&,vRefNum%) IF maxFile% THEN FN theLF(_MactoMSDOS,filename$,vRefNum%) END FN '--------------------------------------------------------------------- ' "メインルーチン、イベントループ処理(自動)" '--------------------------------------------------------------------- WINDOW OFF: '"起動時にウィンドウを表示しないように指定" FN initMenu: '"メニューの構築" ON MENU FN doMenu: '"メニューイベントが発生したときの飛び先" FN dragDrop DO HANDLEEVENTS: '"イベントループ" UNTIL gQuit_flag