[BlueLeaf1336]>
PROGRAM>
エクスプローラからのドラッグ&ドロップ受付
2003/09/20:作成
2003/04/07:開始・停止をコマシに
比較的簡単に、自分のアプリケーションがエクスプローラからのドラッグ&ドロップを受け付けるようにできるクラスです。
しかも、コンポーネントパレットを汚しません。
インスタンスの作成時に、ドロップを受け付けるコンポーネント(たとえばTMemoとかTEditなど)と、受け付け通知用の関数を引数に渡してやるだけでOKです。
でもひょっとしたら、クラス側で通知用関数の呼び出し前に受付を一時停止して、関数呼び出し後に再開するような処理がいるような気がします。
受付関数の処理が何十秒とかかる場合、もっかいドロップされてしまったらどうなるの?みたいな不安が...
http://www.psn.ne.jp/~nagayama/program/0017.html
iDragDrop.zip(2,203bytes):ソース
unit iDragDrop;
interface
uses
Windows, Messages, Classes, Controls;
type
TOnShellDropped = procedure(AFiles, AFolds: TStringList;
AControl: TControl; APos: TPoint) of object;
TShellDrop = class
private
FTarget : TWinControl;
FOldWndProc : Pointer;
FNewWndProc : Pointer;
FWndHandle : HWND;
FEnabled : Boolean;
DropFileList: TStringList;
DropFoldList: TStringList;
DropPos : TPoint;
DropControl : TControl;
FOnDropped : TOnShellDropped;
procedure WndProc(var Msg: TMessage); virtual;
procedure UpdateDropList(AFileName: string);
public
constructor Create(ATarget: TWinControl; AOnDropped: TOnShellDropped);
destructor Destroy; override;
procedure Start();
procedure Stop();
published
end;
implementation
uses
ShellApi, SysUtils, Forms;
procedure TShellDrop.UpdateDropList(AFileName: string);
begin
if DirectoryExists(AFileName) then
begin
DropFoldList.Add(AFileName);
end else
if FileExists(AFileName) then
begin
DropFileList.Add(AFileName);
end else
begin
;
end;
end;
constructor TShellDrop.Create(ATarget: TWinControl; AOnDropped: TOnShellDropped);
begin
FTarget := ATarget;
FWndHandle := FTarget.Handle;
FOnDropped := AOnDropped;
DropFileList := TStringList.Create;
DropFoldList := TStringList.Create;
DropPos := Point(-1, -1);
DropControl := nil;
FEnabled := False;
FNewWndProc := Classes.MakeObjectInstance(WndProc);
FOldWndProc := Pointer(SetWindowLong(FWndHandle,GWL_WNDPROC,LongInt(FNewWndProc)));
end;
destructor TShellDrop.Destroy;
begin
if FEnabled then Stop();
SetWindowLong(FWndHandle, GWL_WNDPROC, LongInt(FOldWndProc));
DropFileList.Free;
DropFoldList.Free;
DropPos := Point(-1, -1);
DropControl := nil;
inherited;
end;
procedure TShellDrop.WndProc(var Msg: TMessage);
var
WMDropFiles: TWMDropFiles;
i : integer;
FileName : array [0..255] of Char;
FileCount : integer;
begin
if (Msg.Msg = WM_DROPFILES) then
begin
WMDropFiles := TWMDropFiles(Msg);
try
DragQueryPoint(WMDropFiles.Drop, DropPos);
DropControl := FindDragTarget(FTarget.ClientToScreen(DropPos), False);
FileCount := DragQueryFile(WMDropFiles.Drop, $FFFFFFFF, FileName, SizeOf(FileName));
DropFileList.Clear;
DropFoldList.Clear;
for i := 0 to FileCount - 1 do
begin
DragQueryFile(WmDropFiles.Drop, i, FileName, SizeOf(FileName));
UpdateDropList(FileName);
end;
DragFinish(WmDropFiles.Drop);
FOnDropped(DropFileList, DropFoldList, DropControl, DropPos);
except
Application.HandleException(Self);
end;
end else
begin
Msg.Result := CallWindowProc(FOldWndProc, FWndHandle, Msg.Msg, Msg.wParam, Msg.lParam);
end;
end;
procedure TShellDrop.Start();
begin
if FEnabled then exit;
DragAcceptFiles(FWndHandle, true);
FEnabled := True;
end;
procedure TShellDrop.Stop();
begin
if not FEnabled then exit;
DragAcceptFiles(FWndHandle, False);
FEnabled := False;
end;
end.
unit Main;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
procedure DroppedAction(AFiles, AFolds: TStringList; AControl: TControl; APos: TPoint);
public
end;
var
Form1: TForm1;
implementation
uses
iDragDrop;
var
Dropper: TShellDrop;
procedure TForm1.DroppedAction(AFiles, AFolds: TStringList; AControl: TControl; APos: TPoint);
begin
Memo1.Clear;
Memo1.Lines.Add(StringOfChar('=', 50));
Memo1.Lines.Add(AControl.Name);
Memo1.Lines.Add(StringOfChar('=', 50));
Memo1.Lines.Add(Format('X%3d:Y%3d', [APos.X, APos.Y]));
Memo1.Lines.Add(StringOfChar('=', 50));
Memo1.Lines.AddStrings(AFiles);
Memo1.Lines.Add(StringOfChar('=', 50));
Memo1.Lines.AddStrings(AFolds);
Memo1.Lines.Add(StringOfChar('=', 50));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Dropper := TShellDrop.Create(Memo1, DroppedAction);
Dropper.Start();
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Dropper.Free;
end;
end.