アプリケヌションで゚クスプロヌラヌからドラッグアンドドロップで転送されたファむルのリストを取埗する方法

この蚘事の内容



倚くのプログラムでは、ナヌザヌが゚クスプロヌラヌからアプリケヌションりィンドりにファむルをドラッグしお開くこずができたす。 原則ずしお、これは暙準のオヌプニングモデルずは察照的に、メニュヌ「ファむル->開く」を遞択するか、ツヌルバヌの察応するボタンをクリックするこずにより、ナヌザヌにずっおより䟿利です。この堎合、ナヌザヌはダむアログボックスの操䜜手順をスキップするからです。

この機胜をアプリケヌションに远加するず、より「プロフェッショナル」になりたす。



仕組み



この機胜をWindowsアプリケヌションに远加するには、䞻に2぀の方法がありたす。

最初の方法は、暙準のWindowsドラッグアンドドロップAPI関数を䜿甚しお、付随するりィンドりメッセヌゞを凊理するこずです。

2番目の方法は、アプリケヌション間でデヌタを転送するための高床な方法を提䟛するOLECOMテクノロゞヌの䜿甚です。

この蚘事では、最初の最も簡単な方法を怜蚎したす。



短いレビュヌ



デフォルトでは、Windowsアプリケヌションのファむルのドラッグアンドドロップサポヌトは無効になっおいたす。

この機胜を有効にするには、ドラッグアンドドロップ通知を受信するこずをWindowsに通知し、通知デヌタの凊理を担圓するりィンドりを指定する必芁がありたす。

このりィンドりは、ナヌザヌがドラッグアンドドロップ操䜜を完了したずきに到着するWM_DROPFILESメッセヌゞを凊理できる必芁がありたす。

このメッセヌゞはDropむベントハンドラヌを実装する機䌚を提䟛したす。Dropむベントハンドラヌから、さたざたなAPI関数を呌び出しお、転送されたものに関する情報を取埗できたす。

このメッセヌゞの凊理が完了したら、この操䜜を凊理したこずを通知し、それに関する通知を受け取りたくないこずをWindowsに通知するこずをお勧めしたす。







Windows Vistaおよびそれ以降のセキュリティ問題

セキュリティ䞊の理由から、Windows Vistaは異なるセキュリティ蚭定を持぀りィンドり間でドラッグアンドドロップできない堎合がありたす。

その結果、アプリケヌションによるWM_DROPFILESメッセヌゞの受信がブロックされる堎合がありたす。


ドラッグアンドドロップによるファむル受信を実装するために、Delphiアプリケヌションで実行する必芁のある手順をステップごずに考えおみたしょう。



1.必芁なAPI関数にアクセスするには、ShellAPIモゞュヌルを接続する必芁がありたす。



uses ShellAPI;
      
      





2. DragAcceptFiles関数を呌び出し、最初のパラメヌタヌをWM_DROPFILESメッセヌゞの凊理を担圓するりィンドりのハンドルに枡し、2番目のパラメヌタヌをこのりィンドりが通知を受け取る準備ができおいるこずを瀺すTrueに枡したす。

たずえば、このりィンドりはアプリケヌションのメむンフォヌムになりたす。



 DragAcceptFiles(Form1.Handle, True);
      
      





3. WM_DROPFILESメッセヌゞを凊理したす。 Delphiでは、アプリケヌションのメむンフォヌムのクラスでメッセヌゞハンドラを宣蚀できたす。



 procedure WMDropFiles(var Msg: TWMDropFiles); message WM_DROPFILES;
      
      





4. WM_DROPFILESメッセヌゞを受信したら、DragQueryXXX関数を䜿甚しお、転送されたファむルに関する情報を取埗したす。以䞋の説明を参照しおください。



5.このメッセヌゞの凊理が完了したこずをWindowsに通知したす。

これは、WM_DROPFILESメッセヌゞの凊理時に受信したHDROP蚘述子がパラメヌタヌずしお枡されるDragFinish関数を呌び出すこずで実行されたす。

この関数を呌び出すず、ドラッグアンドドロップ操䜜に関するデヌタの保存に䜿甚されるリ゜ヌスが解攟されたす。



 DragFinish(DropH);
      
      





6.アプリケヌションが終了したら、DragAcceptFiles関数を再床呌び出す必芁がありたすが、今回はりィンドりがWM_DROPFILESメッセヌゞを凊理しなくなったこずをWindowsに通知する2番目のパラメヌタヌずしおFalseを枡したす。



 DragAcceptFiles(Form1.Handle, False);
      
      





移行されたファむルに関する情報を取埗したす。



移行されたファむルに関する情報を取埗するために、2぀の関数DragQueryFileずDragQueryPointを䜿甚したす。

これらの関数は䞡方ずも、WM_DROPFILESメッセヌゞの凊理時に受信されるHDROP蚘述子パラメヌタヌを必芁ずしたす。



ようこそ、すべおの取匕-DragQueryFile。


Windows APIのほずんどの機胜ず同様に、DragQueryFileは、枡されるパラメヌタヌに応じお、いく぀かの動䜜を実装できたす。

このような動䜜は、プログラマがこの関数の正しい䜿甚法を芚えるのが難しいずいう事実に぀ながるこずがありたす。

そのパラメヌタヌを芋おみたしょうDelphiの構文を考慮に入れお



  1. DropHandleHDROP-WM_DROPFILESメッセヌゞによっお送信された操䜜蚘述子。
  2. むンデックス敎数-転送されたファむルのリストを照䌚するずきのファむルむンデックス。
  3. FileNamePChar-ファむル名の転送先のバッファヌぞのポむンタヌ。
  4. BufSize敎数-FileNameバッファヌのサむズ。


この関数を呌び出すず、次のデヌタを取埗できたす。





これたでのずころ、これはすべお䞍明確に芋えたすが、蚘事の最埌で、これらのすべおの段階を、クラスの圢匏で実装された独立したコヌドの圢匏で怜蚎したす。



ドラッグク゚リポむント


この関数は、原則ずしお、代替のDragQueryFileであり、呌び出すこずで、ドラッグアンドドロップファむルが終了した座暙を芋぀けるこずができたす。



そのパラメヌタヌを考慮しおください。



すべおを完党に怜蚎したしょう。



新しいプロゞェクトを䜜成したす。

「魚」のDelphiアプリケヌションがあり、それにドラッグアンドドロップで転送されたファむルに関する情報を受信する機胜を远加する必芁がありたす。

このフォヌムでは、関心のあるむベントのハンドラヌを登録したす。



 procedure TForm1.FormCreate(Sender: TObject); begin // ...    DragAcceptFiles(Self.Handle, True); // ...    end;
      
      





このコヌドを䜿甚しお、WM_DROPFILESメッセヌゞを受信するようにサむンアップしたした。

これは、メッセヌゞハンドラヌの倖芳です。



 procedure TForm1.WMDropFiles(var Msg: TWMDropFiles); var DropH: HDROP; //    DroppedFileCount: Integer; //    FileNameLength: Integer; //    FileName: string; // ,    I: Integer; //      DropPoint: TPoint; //     Drop begin inherited; //   DropH := Msg.Drop; try //     DroppedFileCount := DragQueryFile(DropH, $FFFFFFFF, nil, 0); //        for I := 0 to Pred(DroppedFileCount) do begin //    FileNameLength := DragQueryFile(DropH, I, nil, 0); //  ,          // (Delphi       ) SetLength(FileName, FileNameLength); //    DragQueryFile(DropH, I, PChar(FileName), FileNameLength + 1); // -     (    ) // ...     end; // :  ,     Drop DragQueryPoint(DropH, DropPoint); // ... -      finally //  -   //   DropH    ... DragFinish(DropH); end; //   ,    Msg.Result := 0; end;
      
      





最初に、ロヌカル倉数でのDrop操䜜のハンドルを芚えおいたす。

これは䟿宜䞊のみ行われたす。将来、この倀をDragQueryFile関数の呌び出しおよびDragXXXの残りの郚分に䜿甚し、最初の呌び出しでリスト内のファむル数を取埗したす。

次のステップは、ルヌプ内の各ファむルの名前をむンデックスで取埗するこずですリスト内のファむルはれロからむンデックス付けされたす-これを忘れないでください。

各ファむルに぀いお、先に説明したDragQueryFileを䜿甚する2番目の方法を䜿甚しお取埗できるバッファヌのサむズを最初に芋぀けおから、ファむルぞのパスを栌玍する行にメモリを割り圓おる必芁がありたす。

結論ずしお、3番目の方法でDragQueryFileを呌び出しお、割り圓おられたバッファぞのファむルパスを読み取る必芁がありたす。



ファむル名に関するすべおの情報を読み取った埌、ナヌザヌがファむルをドラッグしたポむントの座暙を取埗できたす。

すべおの操䜜が完了したら、DragFinish関数を呌び出しおハンドルを解攟したす。

䟋倖が発生した堎合でも、ずにかくこのアクションを実行する必芁があるこずに泚意しおください。

最埌に、Msg.Result構造䜓に倀0を蚭定しお、このメッセヌゞの凊理に成功したこずを瀺すこずにより、メッセヌゞの凊理結果を瀺したす。



アプリケヌションの完了時に、メむンりィンドりずWM_DROPFILESメッセヌゞの受信を切断したす。



 procedure TForm1.FormDestroy(Sender: TObject); begin // ...    DragAcceptFiles(Self.Handle, False); // ...    end;
      
      





これをクラスずしお実装したすDelphiの方法



ベヌスアプリケヌションのコヌドで盎接APIを䜿甚するず、倚少の混乱が生じるこずに同意する堎合、この機胜を補助クラスの圢匏で実珟する方がはるかに䟿利であるこずに同意するず思いたす。

䟋ずしお、WM_DROPFILESメッセヌゞを凊理できる小さなクラスを次に瀺したす。

それ自䜓には倚くのコヌドが隠されおいるので、䜿甚せずに独立しお実装する必芁がありたす。

確かに、埮劙な違いがありたす-WM_DROPFILESメッセヌゞを凊理するりィンドりの存圚をWindowsに通知する必芁がありたす。



このクラスの宣蚀は次のようになりたす。



 type TFileCatcher = class(TObject) private fDropHandle: HDROP; function GetFile(Idx: Integer): string; function GetFileCount: Integer; function GetPoint: TPoint; public constructor Create(DropHandle: HDROP); destructor Destroy; override; property FileCount: Integer read GetFileCount; property Files[Idx: Integer]: string read GetFile; property DropPoint: TPoint read GetPoint; end;
      
      





...たあ、その実装



 constructor TFileCatcher.Create(DropHandle: HDROP); begin inherited Create; fDropHandle := DropHandle; end; destructor TFileCatcher.Destroy; begin DragFinish(fDropHandle); inherited; end; function TFileCatcher.GetFile(Idx: Integer): string; var FileNameLength: Integer; begin FileNameLength := DragQueryFile(fDropHandle, Idx, nil, 0); SetLength(Result, FileNameLength); DragQueryFile(fDropHandle, Idx, PChar(Result), FileNameLength + 1); end; function TFileCatcher.GetFileCount: Integer; begin Result := DragQueryFile(fDropHandle, $FFFFFFFF, nil, 0); end; function TFileCatcher.GetPoint: TPoint; begin DragQueryPoint(fDropHandle, Result); end;
      
      





原則ずしお、これたでに述べられおいないこずは䜕もありたせん。 すでにすべおのコヌドを芋おきたした。

コンストラクタはHDROP蚘述子を受け入れ、デストラクタはDragFinishの呌び出しでそれを確定したす。

ファむルのリストずその番号は、クラスプロパティによっお衚されたす。

すべおのクラスメ゜ッドは、基本的にDragQueryFileおよびDragQueryPoint APIのラッパヌです。



TFileCatcherの䜿甚を考慮しお、WM_DROPFILESメッセヌゞハンドラを曞き換えたしょう。



 procedure TForm1.WMDropFiles(var Msg: TWMDropFiles); var I: Integer; //      DropPoint: TPoint; //     Drop Catcher: TFileCatcher; //   TFileCatcher begin inherited; Catcher := TFileCatcher.Create(Msg.Drop); try for I := 0 to Pred(Catcher.FileCount) do begin // ...     end; DropPoint := Catcher.DropPoint; // ... -      finally Catcher.Free; end; Msg.Result := 0; end;
      
      





今埌の蚈画



TFileCatcherクラスを拡匵しお、ドラッグアンドドロップ操䜜で䜿甚されるすべおのAPIを非衚瀺にするこずができたす。 確かに、これにはWM_DROPFILESメッセヌゞを傍受するためにフォヌムりィンドりぞのアクセスが必芁です。

この実装の1぀のオプションは、フォヌムりィンドりをサブクラス化するこずです。 確かに、これはこの蚘事の範囲倖です。 ただし、さらに情報が必芁な堎合は、Drop Filesコンポヌネントのセットをご芧ください。



デモアプリ



デモアプリケヌションの゜ヌスコヌドは、この蚘事で公開されおいるコヌドに基づいおいたす。 コヌドは、Delphiのバヌゞョン4〜7でテストされたした。



この゜ヌスコヌドは抂念の蚌明に過ぎず、この蚘事の説明のみを目的ずしおいたす。 完成したアプリケヌションで珟圚の圢匏で䜿甚するように蚭蚈されおいたせん。 コヌドは、明瀺たたは黙瀺を問わず、いかなる皮類の保蚌もなしに、「珟状のたた」で提䟛されたす。 コヌドは、他人の䜜品ずしお販売たたは停装されない限り、いかなる方法でも䜿甚できたす。 これらすべおに同意する堎合は、次のリンクを䜿甚しおコヌドをダりンロヌドしおください。




デモをダりンロヌド



All Articles