procedure TForm1.FormCreate(Sender: TObject);
begin
//ドラッグアンドドロップの受け入れ許可
DragAcceptFiles(Handle, True);
end;
//ドラッグアンドドロップ
procedure TForm1.WMDropFiles(
var Msg: TWMDROPFILES);
var
i, li_Buff: Integer;
ls_PWFile: PWideChar;
lsl_List: TStrings;
begin
DragAcceptFiles(Handle, False);
//ドロップの処理中はドロップを受け付けない
lsl_List := TStringList.Create;
try
try
//ドロップされたファイルの数だけ処理を行う
for i := 0
to DragQueryFileW(Msg.Drop, $FFFFFFFF,
nil, 0) - 1
do begin
li_Buff := DragQueryFileW(Msg.Drop,
i,
nil, 0);
ls_PWFile := AllocMem((li_Buff + 1) * 2);
try
DragQueryFileW(Msg.Drop, i, ls_PWFile,
li_Buff + 1);
lsl_List.Add(
gfnsWideToAnsiEx(
WideString(ls_PWFile)));
finally
FreeMem(ls_PWFile);
end;
end;
finally
DragFinish(Msg.Drop);
//ドロップハンドルを解放
end;
//-------------------------------------------------
//ここにリストを使った何らかの処理
//リストを使うときはgfnsAnsiToWideEx関数で戻してから使う
//-------------------------------------------------
finally
lsl_List.Free;
end;
DragAcceptFiles(Handle, True);
//処理が終わったのでドロップの受け入れを許可
end;
//ドラッグアンドドロップ
procedure TForm1.WMDropFiles(
var Msg: TWMDROPFILES);
function lfnrc_OriginRect(Control: TControl): TRect;
//コントロールのBoundsRectをスクリーン座標で返す
begin
with Control
do begin
if (Parent =
nil)
or (Parent.Handle = Application.Handle)
then begin
Result := BoundsRect;
end else begin
Result := Rect(
Parent.ClientToScreen(Point(Left, Top)),
Parent.ClientToscreen(Point(Left + Width, Top + Height))
);
end;
end;
end;
function lfnrc_ClientOriginRect(Control: TControl): TRect;
//コントロールのClientRectをスクリーン座標で返す
begin
with Control
do begin
Result := Rect(
ClientToScreen(Point(0, 0)),
ClientToscreen(Point(ClientWidth, ClientHeight))
);
end;
end;
function lfnctl_ControlGet(ptPos: TPoint; WinControl: TWinControl): TControl;
//WinControl上でptPos(スクリーン座標)上にある一番手前のコントロールを返す
var
i: Integer;
begin
Result :=
nil;
with WinControl
do begin
//WinControlの領域内か?
if (PtInRect(lfnrc_OriginRect(WinControl), ptPos))
then begin
//クライアント領域内か?
if (PtInRect(lfnrc_ClientOriginRect(WinControl), ptPos))
then begin
//クライアント領域内
for i := ControlCount -1
downto 0
do begin
if (Controls[i]
is TWinControl)
then begin
//WinControlの場合は子コントロールがあるかもしれないので再起呼び出しを行う
Result := lfnctl_ControlGet(ptPos,
TWinControl(Controls[i]));
//Resultがnilでないということは該当するコントロールがあった
if (Result <>
nil)
then begin
Break;
end;
end else begin
if (PtInRect(lfnrc_ClientOriginRect(Controls[i]), ptPos))
then begin
Result := Controls[i];
Break;
end;
end;
end;
if (Result =
nil)
then Result := winControl;
end else begin
//クライアント領域外だけどWinControl領域内(例えばタイトルバーとか)
Result := WinControl;
end;
end;
end;
end;
var
i, li_Buff: Integer;
ls_PWFile: PWideChar;
lsl_List: TStrings;
l_DropControl: TControl;
lpt_DropPos: TPoint;
begin
DragAcceptFiles(Handle, False);
DragQueryPoint(Msg.Drop, lpt_DropPos);
//lpt_DropPosはフォームのクライアント座標
//ドロップされたコントロールを取得
l_DropControl := lfnctl_ControlGet(Self.ClientToScreen(lpt_DropPos),
Self);
if (l_DropControl <> Self)
then begin
//フォームのクライアント座標のlpt_DropPosをl_DropControlのクライアント座標に変換
lpt_DropPos := l_DropControl.ScreenToClient(Self.ClientToScreen(lpt_DropPos));
end;
//ドロップされたファイルをリストに取得
lsl_List := TStringList.Create;
try
try
//ドロップされたファイルの数だけ処理を行う
for i := 0
to DragQueryFileW(Msg.Drop, $FFFFFFFF,
nil, 0) - 1
do begin
li_Buff := DragQueryFileW(Msg.Drop,
i,
nil, 0);
ls_PWFile := AllocMem((li_Buff + 1) * 2);
try
DragQueryFileW(Msg.Drop, i, ls_PWFile,
li_Buff + 1);
//オリジナルの変換関数を使ってWideStringをリストに持たせる
lsl_List.Add(
gfnsWideToAnsiEx(
WideString(ls_PWFile)));
finally
FreeMem(ls_PWFile);
end;
end;
finally
DragFinish(Msg.Drop);
//ドロップハンドルを解放
end;
//--------------------------------------------------
//ここにリストやコントロールなどを使った何らかの処理
//リストを使うときはgfnsAnsiToWideEx関数で戻してから使う
//--------------------------------------------------
finally
lsl_List.Free;
end;
DragAcceptFiles(Handle, True);
//処理が終わったのでドロップの受け入れを許可
end;
l_DropControl には TPanel や TListBox 等の TWinControl だけでなく TLabel
や TImage 等のウィンドウハンドルを持たないコントロールも返ります。
また lpt_DropPos には Form1 のクライアント座標ではなく、ドロップされたコントロールのクライアント座標での値が入ります。