[Delphi] ファイルのドラッグ&ドロップ

TControl を継承したオブジェクトはドラッグ&ドロップ関連のプロパティやメソッドを持つが、これはそのアプリ内でDelphiのコンポーネントをドラッグする場合にしか使用できない。プロセス外からのドロップを受け取るには、Windows API を使用する必要がある。
ドロップを受け取る Delphi コンポーネント側で、DragAcceptFile を使用して Windows にドロップを受け取ることを伝える。(ShellAPI を uses に追加する必要があります。)
下記は TForm1 でドロップを受け取るための例。

  TForm1.Create(AOwner: TComponent);
  begin
    inherited;
    DragAcceptFiles(Handle, True);
  end;

これで、このForm上にファイルをドラッグすると、マウスカーソルがドロップ可能な形状になる。
実際にドロップが発生すると、WM_DROPFILES メッセージが発生するので、このメッセージのハンドラを作成する。

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

ドロップされたファイル名の取得は、DragQueryFile を使う。ドロップされた個数を調べるには、以下のようにする。

  hDrop := THandle(Msg.Drop);
  DropCount := DragQueryFile(hDrop, UINT(-1), nil, 0);

個々のファイル名の処理は、以下のようにする。

var
  hDrop: THandle;
  i: Integer;
  FileName: PChar;
begin
  FileName := StrAlloc(MAX_PATH);
  for i := 0 to Pred(DropCount) do
  begin
    DragQueryFile(hDrop, i, FileName, MAX_PATH - 1);    // FileNameの処理
    ListBox1.Items.Add(StrPas(FileName));               // 処理の一例
  end;
end;

MainFormのどこにドロップしたか知りたい場合は、DragQueryPointを使用する。
※注意 ドロップ処理が終わってファイル名を格納した領域が不要になったところで使用したメモリの解放が必要。

DragFinish(hDrop); 

まとめると...

procedure TForm1.WMDropFiles(var Msg: TWMDropFiles);
var
  hDrop: THandle;
  i, DropCount: Integer;
  FileName: PChar;
begin
  hDrop := THandle(Msg.Drop);
  try
   FileName := StrAlloc(MAX_PATH);
   DropCount := DragQueryFile(hDrop, UINT(-1), nil, 0);
    for i := 0 to Pred(DropCount) do
    begin
      DragQueryFile(hDrop, i, FileName, MAX_PATH - 1);    // FileNameの処理
      ListBox1.Items.Add(StrPas(FileName));               // 処理の一例
    end;
  finally
    DragFinish(hDrop);
  end;
end;

Delphi2005 Win32, Delphi 2010で動作確認を実施。

コメント (0件)


くろねこ研究所
https://www.blackcat.xyz/article.php/ProgramingFAQ_del0059