ウィンドウメッセージの割り込み処理の機能を使った最初に紹介する拡張機能は、HSPウィンドウにドラッグ・アンド・ドロップされたファイルの取得です。
ドラッグ・アンド・ドロップされたファイル名を取得する機能を使うには、以下のような操作を行います。
まずは、処理を行うウィンドウメッセージの登録からです。ファイルがウィンドウにドラッグ・アンド・ドロップされると、そのウィンドウには
メッセージが送られます。このメッセージコードは次のように定義されています。このメッセージの付加情報として渡されるwParamパラメータの値はドロップされたファイルの名前を管理している内部データ構造体を識別するハンドルであり、後でファイル名を取得するにはこのハンドルが必要になります。
このメッセージのlParamパラメータは使われません。常に0が渡されます。
次に、ウィンドウがファイルがドロップされるファイルを受け取るのを許可する設定をします。ウィンドウにドロップ出来るようにするには、DragAcceptFiles関数を使います。この関数はshell32.dllによって提供されており、次のように定義されています。
VOID DragAcceptFiles( HWND hWnd, // window handle BOOL fAccept // accept flag );
hWndパラメータには対象ウィンドウのハンドルを、fAcceptパラメータにはファイルのドラッグ・アンド・ドロップを許可するかどうかを表す値を指定します。ファイルをドロップできるようにするにはfAcceptパラメータに1 (TRUE) を、ドロップできないようにするには0 (FALSE) を指定します。
この関数でドラッグ・アンド・ドロップを許可するように設定したら、あとはメッセージが送られてくるのを待ちます。ドラッグアンドドロップされると、ウィンドウに
メッセージが送られてきます。ウィンドウに
メッセージが送信されたとき、wParamパラメータとして渡される内部構造体のハンドルを用いることによって、次の情報を得ることができます。まずはドロップされたファイルの数を取得する必要があります。ファイル数を取得するには、shell32.dllが提供するDragQueryFile関数を使います。
UINT DragQueryFileA( HDROP hDrop, // internal structure handle UINT iFile, // file index PTSTR pszFile, // buffer for file name UINT cch // buffer size );
ファイル数を取得する場合は、この関数のhDropパラメータに先ほどの内部構造体のハンドルを指定し、iFileパラメータに-1を指定します。pszFileパラメータとcchパラメータにはそれぞれ0 (NULL) と0を指定します。こうすることで、関数の戻り値としてファイル数が返ります。
次にファイル名を取得します。ファイル名の取得は1つずつ行います。使用するAPI関数は、ファイル数取得のときと同様にDragQueryFile関数です。今度は、iFileパラメータにファイルのインデックスを、pszFileパラメータには、ファイル名を格納するための文字列変数のアドレスを指定しておきます。このパラメータには、260バイト以上のサイズを確保した文字列型変数のアドレスを指定しましょう。また、cchパラメータにはその変数のサイズ(すなわち260)を指定します。ファイルのインデックスは0を基準としたものになります。したがって、1つ目のファイルを取得するならインデックスを0に、2つ目なら1に、……というようにして、これをドロップされたファイルの数だけ繰り返します。
ファイルがウィンドウのどの座標にドロップされたかを取得することもできます。これには、shell32.dllのDragQueryPoint関数を呼び出します。
DWORD DragQueryPoint( HDROP hDrop, // internal structure handle PPOINT ppt // POINT structre );
最初のhDropパラメータには、ドロップファイルの情報を持つ内部構造体のハンドルを指定します。pptパラメータには、ドロップされた座標を格納するためのPOINT構造体のアドレスを指定します。
POINT構造体は点の座標を格納するための構造体で、以下のように定義されています。
typedef struct tagPOINT { LONG x; // x-coordinate LONG y; // y-coordinate } POINT, *PPOINT, *NPPOINT, *LPPOINT;
この構造体のxメンバとyメンバには、それぞれ点のx座標とy座標が格納されます。DragQueryPoint関数にこの構造体を渡すと、ファイルがドロップされた点の座標がクライアント座標の形で格納されます。
必要なデータがすべて取得し終わったら、DragFinish関数を呼び出します。
VOID DragFinish( HDROP hDrop // internal structure handle );
ファイルがドロップされると、システムは自動的にメモリを確保してドロップされたファイルの情報を保持しています。DragFinish関数は、このメモリ領域を解放するためのものです。
DragAcceptFiles関数によってファイルのドラッグ・アンド・ドロップを許可するように設定する場合には、必ず メッセージに対する処理を行うようにしてください。そして、メッセージ処理の際には、DragFinish関数を使って、必ずハンドルを解放するようにしてください。これらのことを怠ると、アプリケーションがメモリリークを起こしてしまう可能性があります。
さて、実際にスクリプトを書いてみます。ウィンドウにファイルがドラッグ・アンド・ドロップされたらそのファイル名を表示するプログラムを作ります。
#uselib "shell32.dll" #func DragAcceptFiles "DragAcceptFiles" int,int #func DragQueryFile "DragQueryFileA" int,int,int,int #func DragQueryPoint "DragQueryPoint" int,int #func DragFinish "DragFinish" int #define WM_DROPFILES 0x0233 ; メッセージ処理の登録 oncmd gosub *OnDropFiles, WM_DROPFILES ; ドロップファイルの受け入れを設定 DragAcceptFiles hwnd, 1 if stat == 0 { dialog "設定に失敗しました。", 1, "エラー" end } mes "このウィンドウにファイルをドロップして下さい。" stop *OnDropFiles ; ====== ファイルがドロップされたときの処理 ====== hDrop = wparam ; データ構造体のハンドル ; ファイルがドロップされた座標の取得 dim point, 2 ; POINT 構造体 DragQueryPoint hDrop, varptr(point) mes "ドロップ座標 ( " + point(0) + ", " + point(1) + " )" ; ファイルの数の取得 DragQueryFile hDrop, -1, 0, 0 ; 第2パラメータを -1 に filecount = stat ; ドロップされたファイル数 mes "ファイル数 " + filecount + " 個" ; ファイル名の取得(ドロップされたファイルの数だけ実行) sdim filename, 260 ; ファイル名を格納するバッファ repeat filecount DragQueryFile hDrop, cnt, varptr(filename), 260 mes filename ; ファイル名を表示 loop ; ドロップファイル用のメモリを解放 DragFinish hDrop return 0