안녕 하십니까.. ^^
늘 도움만 받아가는 초봅니다 ~
FTP 같은 어플리케이션을 구현하려다가
문제가 좀 있어서 여기저기 검색하다가 이 정욱님께서 올린 글을 보았습니다.
제 어플리케이션의 LIstView 에 서버에 저장돼어있는 파일의 List 들이 잇습니다.
이 Listview 에서 드래그해서 바탕화면이나 탐색기에 드랍을 시킬때 Target 이 돼는 바탕화면이나 탐색기의 Fullpath 가 어떻게 돼는지 알고싶어서요..
.
이정욱 님께서는 이 문제를 어떻게 처리 하셧는지요 ..
아래는 아주 오랜전에 이정욱 님께서 올리신 글입니다 ~ ~
[질문]Drag&Drop에 관하여... ^^;
안녕하세요?
답변만 하다가 질문도 하네요.. 히..
Drag&Drop을 하는데 생각보다 어렵네요.
바탕화면에 있는것이라던가 탐색이에 있는것을 내쪽으로 끌어오는것을 할 수 있겠는데 문제는 내쪽에 있는 객체나 파일을 바탕화면이나 탐색기로 끌어다가 놓으려니 그게 조금 어렵네요.
누구의 말로는 COM객체를 사용해서 한다고 하지만 전 잘 모르겠어요..흑...
혹시 이것에 대해 잘 아시는 분 계시면 답변좀 부탁드립니다.
감사합니다.
도움 되셨으면 좋겠네요...
그럼...
<!--CodeS-->
{This example will show you how your application
will be able to copy files from your application to
Windows Explorer using Drag'n' Drop.
Exactly the way it is done by the OS itself!
Create a new application containing just one unit,
called 'Unit1'. Drop a FileListBox and a DirectoryListBox on to the form,
leave their names the way they are.
Connect FileListBox1 with DirectoryListBox1 by setting the FileList-property of
DirectoryListBox1. Make sure that the MultiSelect-property of FileListBox1 is set to 'True'!
The best thing you can do now is to replace all text with the code below:}
//---------------------------------------------
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs,
StdCtrls, FileCtrl, ActiveX, ShlObj, ComObj;
type
TForm1 = class(TForm, IDropSource)
DirectoryListBox1: TDirectoryListBox;
FileListBox1: TFileListBox;
procedure FileListBox1MouseDown(Sender: TObject; Button:
TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FileListBox1MouseMove(Sender: TObject; Shift: TShiftState;
X,
Y: Integer);
private
FDragStartPos: TPoint;
function QueryContinueDrag(fEscapePressed: BOOL;
grfKeyState: Longint): HResult; stdcall;
function GiveFeedback(dwEffect: Longint): HResult; stdcall;
public
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
function GetFileListDataObject(const Directory: string; Files:
TStrings):
IDataObject;
type
PArrayOfPItemIDList = ^TArrayOfPItemIDList;
TArrayOfPItemIDList = array[0..0] of PItemIDList;
var
Malloc: IMalloc;
Root: IShellFolder;
FolderPidl: PItemIDList;
Folder: IShellFolder;
p: PArrayOfPItemIDList;
chEaten: ULONG;
dwAttributes: ULONG;
FileCount: Integer;
i: Integer;
begin
Result := nil;
if Files.Count = 0 then
Exit;
OleCheck(SHGetMalloc(Malloc));
OleCheck(SHGetDesktopFolder(Root));
OleCheck(Root.ParseDisplayName(0, nil,
PWideChar(WideString(Directory)),
chEaten, FolderPidl, dwAttributes));
try
OleCheck(Root.BindToObject(FolderPidl, nil, IShellFolder,
Pointer(Folder)));
FileCount := Files.Count;
p := AllocMem(SizeOf(PItemIDList) * FileCount);
try
for i := 0 to FileCount - 1 do
begin
OleCheck(Folder.ParseDisplayName(0, nil,
PWideChar(WideString(Files[i])), chEaten, p^[i],
dwAttributes));
end;
OleCheck(Folder.GetUIObjectOf(0, FileCount, p^[0], IDataObject,
nil,
Pointer(Result)));
finally
for i := 0 to FileCount - 1 do begin
if p^[i] <> nil then Malloc.Free(p^[i]);
end;
FreeMem(p);
end;
finally
Malloc.Free(FolderPidl);
end;
end;
function TForm1.QueryContinueDrag(fEscapePressed: BOOL;
grfKeyState: Longint): HResult; stdcall;
begin
if fEscapePressed or (grfKeyState and MK_RBUTTON = MK_RBUTTON) then
begin
Result := DRAGDROP_S_CANCEL
end else if grfKeyState and MK_LBUTTON = 0 then
begin
Result := DRAGDROP_S_DROP
end else
begin
Result := S_OK;
end;
end;
function TForm1.GiveFeedback(dwEffect: Longint): HResult; stdcall;
begin
Result := DRAGDROP_S_USEDEFAULTCURSORS;
end;
procedure TForm1.FileListBox1MouseDown(Sender: TObject;
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
begin
FDragStartPos.x := X;
FDragStartPos.y := Y;
end;
end;
procedure TForm1.FileListBox1MouseMove(Sender: TObject; Shift:
TShiftState;
X, Y: Integer);
const
Threshold = 5;
var
SelFileList: TStrings;
i: Integer;
DataObject: IDataObject;
Effect: LongInt; // DWORD
begin
with Sender as TFileListBox do
begin
if (SelCount > 0) and (csLButtonDown in ControlState)
and ((Abs(X - FDragStartPos.x) >= Threshold)
or (Abs(Y - FDragStartPos.y) >= Threshold)) then
begin
Perform(WM_LBUTTONUP, 0, MakeLong(X, Y));
SelFileList := TStringList.Create;
try
SelFileList.Capacity := SelCount;
for i := 0 to Items.Count - 1 do
if Selected[i] then SelFileList.Add(Items[i]);
DataObject := GetFileListDataObject(Directory, SelFileList);
finally
SelFileList.Free;
end;
Effect := DROPEFFECT_NONE;
DoDragDrop(DataObject, Self, DROPEFFECT_COPY, Effect);
end;
end;
end;
initialization
OleInitialize(nil);
finalization
OleUninitialize;
end.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{
As you might have seen, TForm1 is not only a member of class TForm,
but also of class IDropSource!
Now make sure that the two FileListBox events
'OnMouseMove' and 'OnMouseDown' are set correctly.
Run your application and try out the Drag and Drop feature!
You can select multiple items to drag and press escape to cancel.
The cursor will show you what action will take place.
}
<!--CodeE-->