Operasi Drag Drop dari Windows Explorer ke Kontrol

September 12, 2006 at 11:43 am | Posted in Code Samples, Tutorials | 3 Comments
Tags: , , , , ,

by Zamrony P Juhara

Artikel ini sesungguhnya adalah posting saya di milis Delphindo untuk menjawab pertanyaan mengenai bagaimana mendapatkan daftar nama-nama file yang drag drop dari Windows Explorer ke suatu control. Jika anda pernah menggunakan WinAmp, anda tentu tahu bahwa kita bisa menambahkan file-file musik ke dalam PlayList dengan cara mendrag-drop file-file dari Windows Explorer ke Listbox playList WinAmp.

Pertanyaannya sekarang adalah:Bagaimana?

Mendaftarkan Handle Window

Untuk bisa menerima drag drop dari shell explorer, kita perlu mendaftarkan handle window. Prosesnya dikerjakan dengan
memanggil fungsi DragAcceptFiles() dideklarasi di shellapi.pas

Fungsi ini mengharapkan dua parameter. Parameter pertama adalah handle yang akan menerima proses drag-drop,
parameter kedua memberitahukan tipe proses registrasi atau unregistrasi. Jika true berarti window handle akan menerima pemberitahuan ketika terjadi drag drop dan bila FALSE maka window handle akan dibuang dari daftar handle yang akan menerima pemberitahuan drag drop.

Memproses Message WM_DROPFILES

Message WM_DROPFILES akan dikirim ke handle window yang telah terdaftar untuk menerima notifikasi. wParam akan berisi handle
ke drag dop yangs sedang terjadi. Handle ini selanjutnya dapat kita pergunakan untuk mendapatkan informasi seperti jumlah file yang
di drag drop dan juga nama-nama filenya. Karena menggunakan handle window, hanya kontrol yang memiliki handle window yang dapat
menerima message ini. WM_DROPFILES akan dikirim melalui Window procedure handle yang bersangkutan.

Mendapatkan Jumlah File yang di drag drop

DragQueryFile kita pergunakan untuk mendapatkan jumlah file yang draq

total_file:=DragQueryFile(hDrop,$FFFFFFFF,nil,0);

Fungsi ini butuh empat parameter, tapi untuk mendapatkan info jumlah file hanya dua parameter awal yang relevan. Sisanya kita isi nil dan 0. Parameter pertama adalah handle drag drop, kedua adalah index file, harus kita isi dengan $FFFFFFFF.

Mendapatkan Panjang Nama File yang di drag drop

Kita perlu tahu panjang nama file, agar kita dapat mengalokasikan buffer untuk menampung data nama file ini.
Untuk mendapatkan panjang nama file, kita masih menggunakan fungsi yang sama yakni DragQueyFile(), namun dengan sedikit parameter berbeda, yakni
Fileindex kita isi dengan 0 hingga total_file-1

filename_len:=DragQueryFile(hDrop,FileIndex,nil,0);

Mendapatkan Nama File yang di drag drop

Kita perlu tahu nama file. Untuk mendapatkan nama file, kita gunakan lagi DragQueyFile(),
Fileindex kita isi dengan 0 hingga total_file-1,

DragQueryFile(hDrop,FileIndex,aFilename,filename_len);

afilename adalah data bertipe PChar yang sebelumnya telah dialokasikan buffernya sebanyak filename_len.

Mengakhiri Proses Drag Drop

Kita panggil DragFinish() untuk memberitahukan bahwa kita telah selesai dengan proses drag drop. Fungsi ini akan
membebaskan memori yang dialokasikan untuk menyimpan daftar nama file. Handle drag drop kita lewatkan ke fungsi ini.

Berikutnya kita buat implementasinya. Kita akan mengenkapsulasi fungsionalitas drag drop menjadi satu komponen yang
akan memudahkan proses drag dop ke sebuah kontrol.

berikut ini source code-nya:

{
================================
  TDragDrop v.1.0
=================================
 Komponen yg mengenkapsulasi proses
 drag drop files dari file manager
 ke window control
=================================
(c)2004 Zamrony P Juhara
=================================
}
unit DragDrop;

interface

uses
  SysUtils, Classes,Controls,Windows,Messages;

type
  TDragDropFilesEvent=procedure(Sender:TObject;const FileIndex,TotalFile:integer;
                             const Filename:string) of object;

  TDragDrop = class(TComponent)
  private
    OldWndProc:TWndMethod;
    FAccept: boolean;
    FOnDragDropFiles: TDragDropFilesEvent;
    FControl: TWinControl;
    procedure SetDragAccept;
    procedure WndProc(var msg:TMessage);

    procedure AcceptFiles(const hDrop:THandle);
    function GetTotalDroppedFiles(const hDrop:THandle):integer;
    function GetDroppedFilename(const hDrop:THandle;const FileIndex:integer):string;
    function GetDroppedFilenameLength(const hDrop:THandle;const FileIndex:integer):cardinal;
    procedure AcceptFinish(const hDrop:THandle);

    procedure SetAccept(const Value: boolean);
    procedure SetControl(const Value: TWinControl);
    procedure SetOnDragDropFiles(const Value: TDragDropFilesEvent);
  protected
    procedure DoDragDropFiles(const FileIndex,TotalFile:integer;
                               const Filename:string);virtual;
  public
  published
    property Control:TWinControl read FControl write SetControl;
    property Accept:boolean read FAccept write SetAccept;
    property OnDragDropFiles:TDragDropFilesEvent read FOnDragDropFiles write SetOnDragDropFiles;
  end;

procedure Register;

implementation
uses ShellAPI;

procedure Register;
begin
  RegisterComponents('zaMm Components', [TDragDrop]);
end;

{ TDragDrop }

procedure TDragDrop.AcceptFiles(const hDrop:THandle);
var i,totalFile:integer;
    Filename:string;
begin
  TotalFile:=GetTotalDroppedFiles(hDrop);
  for i:=0 to TotalFile-1 do
  begin
    FileName:=GetDroppedFilename(hDrop,i);
    DoDragDropFiles(i,TotalFile,Filename);
    if Assigned(FOnDragDropFiles) then
      FOnDragDropFiles(Self,i,TotalFile,Filename);
  end;
  AcceptFinish(hDrop);
end;

procedure TDragDrop.AcceptFinish(const hDrop: THandle);
begin
  DragFinish(hDrop);
end;

procedure TDragDrop.DoDragDropFiles(const FileIndex, TotalFile: integer;
  const Filename: string);
begin
//defaultnya gak melakukan apa-apa
//override utk mengubah proses AcceptFiles
end;

function TDragDrop.GetDroppedFilename(const hDrop: THandle;
  const FileIndex: integer): string;
var afilename:PChar;
    size:cardinal;
begin
  result:='';
  size:=GetDroppedFilenameLength(hDrop,FileIndex);
  if Size<>0 then
  begin
    aFilename:=StrAlloc(Size);
    try
      DragQueryFile(hDrop,FileIndex,aFilename,Size);
      result:=aFilename;
    finally
      StrDispose(aFilename);
    end;
  end;
end;

function TDragDrop.GetDroppedFilenameLength(const hDrop: THandle;
  const FileIndex: integer): cardinal;
var size:cardinal;
begin
  size:=0;
  size:=DragQueryFile(hDrop,FileIndex,nil,size);
//tambah satu karena kita menggunakan string
  result:=size+1;
end;

function TDragDrop.GetTotalDroppedFiles(const hDrop: THandle): integer;
begin
  result:=DragQueryFile(hDrop,$FFFFFFFF,nil,0);
end;

procedure TDragDrop.SetAccept(const Value: boolean);
begin
  FAccept := Value;
//kalo runtime
  if not(csDesigning in ComponentState) then
    SetDragAccept;
end;

procedure TDragDrop.SetControl(const Value: TWinControl);
begin
  FControl := Value;
//kalo runtime
  if not(csDesigning in ComponentState) then
    SetDragAccept;
end;

procedure TDragDrop.SetDragAccept;
begin
  if FControl<>nil then
  begin
    if FAccept then
    begin
//kalo accept subclass default window proedure
      OldWndProc:=FControl.WindowProc;
      FControl.WindowProc:=WndProc;
    end else
      FControl.WindowProc:=OldWndProc;

    DragAcceptFiles(FControl.Handle,FAccept);
  end;
end;

procedure TDragDrop.SetOnDragDropFiles(const Value: TDragDropFilesEvent);
begin
  FOnDragDropFiles := Value;
end;

procedure TDragDrop.WndProc(var msg: TMessage);
begin
//msg.WParam berisi handle Drop struktur
  if msg.Msg=WM_DROPFILES then
  begin
    AcceptFiles(msg.WParam);
    msg.Result:=0;
  end else
  OldWndProc(msg);
end;

end.

contoh penggunaan:

Buat aplikasi baru. Drag drop TListbox. Pada formCreate tambahkan baris kode berikut:

procedure TForm1.FormCreate(sender:TObject);
begin
  DragDrop1:=TDragDrop.Create(self);
  DragDrop1.OnDragDropFiles:=DragDropFiles;
  DragDrop1.Control:=ListBox1;
  DragDrop1.Accept:=true;
end;

procedure TForm1.DragDropFiles(Sender: TObject; const FileIndex,
  TotalFile: Integer; const Filename: String);
begin
  ListBox1.Items.Add(Filename);
end;

Tiap kali ada file dari windows explorer didrag drop ke komponen listbox1 maka nama-nama
file yg didrag drop akan ditampilkan di listbox1

Source code bisa di download di sini

3 Comments »

RSS feed for comments on this post. TrackBack URI

  1. Wew, siip, kini gw bisa bikin aplikasi mp3 player yang fantastis, bisa drag & drop langsung dari Windows Explorer. Thansk banget yah Delphindo, vivo Delphindo!!!

  2. kepala hotak kau… aku cai len bagi len
    pedu r……

  3. iyo i.. notepad ku error, bikin pake delphi.. kok ga bisa ngedrag file…. akhirnya bisa , ntar tek coba


Leave a reply to Mozza Cancel reply

Blog at WordPress.com.
Entries and comments feeds.