unit DropFileListView;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ComCtrls;

type
  TDropFiles = procedure (Sender: TObject; Files : TStringList; Point : TPoint) of object;

  TDropFileListView = class(TListView)
  private
    { Private declarations }
    fAcceptFiles : Boolean;
    fOnDropFiles : TDropFiles;

    procedure WMDropFiles(var Message: TMessage); message WM_DROPFILES;

    procedure SetAcceptFiles(Accept : Boolean);
    function GetAcceptFiles : Boolean;

  protected
   procedure Loaded; override;
    { Protected declarations }
  public
    { Public declarations }
  published
    { Published declarations }
    property AcceptFiles : Boolean read GetAcceptFiles write SetAcceptFiles default False;
    property OnDropFiles : TDropFiles read fOnDropFiles write fOnDropFiles default nil;
  end;

procedure Register;

implementation

uses ShellAPI;

procedure Register;
begin
  RegisterComponents('Samples', [TDropFileListView]);
end;

procedure TDropFileListView.WMDropFiles(var Message: TMessage);
var
   Files  : TStringList;
   hDrop  : THandle;
   Buffer : String;
   r      : Integer;
   Count  : Integer;
   i      : Integer;
   Point  : TPoint;
begin
   hDrop := Message.wParam;
   Files := TStringList.Create;
   try
      try
        // Get the count
        Count := DragQueryFile(hDrop, $FFFFFFFF, nil, 0);
        for i := 0 to Count - 1 do
        begin
           SetLength(Buffer, 256);
           r := DragQueryFile(hDrop, i, PChar(Buffer), Length(Buffer));
           SetLength(Buffer, r);
           Files.Add(Buffer);
        end;
        DragQueryPoint(hDrop, Point);
      finally
         DragFinish(hDrop);
      end;

      // Call fOnDropFiles
      if Assigned(fOnDropFiles) then
      begin
         fOnDropFiles(self, Files, Point);
      end

   finally
      Files.Free;
   end;
end;

procedure TDropFileListView.SetAcceptFiles(Accept : Boolean);
begin
   fAcceptFiles := Accept;

  if csDesigning in ComponentState then
  begin
    // Nothing
  end
  else
  begin
    DragAcceptFiles(Handle, fAcceptFiles);
  end;

end;

function TDropFileListView.GetAcceptFiles : Boolean;
begin
   Result := fAcceptFiles;
end;

procedure TDropFileListView.Loaded;
begin
  inherited Loaded;
  if csDesigning in ComponentState then
  begin
    // Nothing
  end
  else
  begin
    DragAcceptFiles(Handle, fAcceptFiles);
  end;
end;

end.
